Update web-platform-tests to revision f7e2ea2c50c4d23549d07cd24c7a96fc3f203d96

This commit is contained in:
WPT Sync Bot 2020-03-12 12:52:18 +00:00
parent 4b1bb895a3
commit 33357a82e4
175 changed files with 1667 additions and 4935 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,4 +0,0 @@
[hit-test-floats-002.html]
[Hit test float]
expected: FAIL

View file

@ -0,0 +1,4 @@
[hit-test-floats-004.html]
[Miss float below something else]
expected: FAIL

View file

@ -0,0 +1,4 @@
[hit-test-floats-005.html]
[Miss clipped float]
expected: FAIL

View file

@ -1,3 +0,0 @@
[ttwf-reftest-flex-wrap-reverse.html]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[ttwf-reftest-flex-wrap.html]
type: reftest
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,4 @@
[traverse_the_history_4.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -0,0 +1,4 @@
[traverse_the_history_5.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -18,6 +18,3 @@
[Set HTTP URL frame location.protocol to ftp]
expected: FAIL
[Set data URL frame location.protocol to file]
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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}

View file

@ -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');

View file

@ -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);
}

View file

@ -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.");

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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");

View file

@ -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>

View file

@ -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>$

View file

@ -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):

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -1 +0,0 @@
Content-Type: text/javascript

View file

@ -1 +0,0 @@
log.push("relative:@std/blank");

View file

@ -1 +0,0 @@
log.push("relative:@std/none");

View file

@ -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>

View file

@ -1 +0,0 @@
Content-Type: text/javascript

View file

@ -1 +0,0 @@
log.push("relative:bare/blank");

View file

@ -1 +0,0 @@
log.push("relative:bare/none");

View file

@ -1 +0,0 @@
log.push("relative:bare/std-blank");

View file

@ -1 +0,0 @@
log.push("relative:bare/std-none");

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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 () => {};
}

View file

@ -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".`]
);
}
});
});

View file

@ -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: []
}
);
});
});

View file

@ -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").'
]
);
});
});

View file

@ -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')]
}
);
});
});

View file

@ -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');
});
});

View file

@ -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/);
});
});

View file

@ -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');
});
});
});

View file

@ -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');
});
});
});

View file

@ -1,5 +0,0 @@
def main(request, response):
return (
(('Content-Type', 'text/javascript'),),
'import "{}";\n'.format(request.GET.first('url'))
)

View file

@ -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);
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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