Auto merge of #25537 - servo-wpt-sync:wpt_update_16-01-2020, r=servo-wpt-sync

Sync WPT with upstream (16-01-2020)

Automated downstream sync of changes from upstream as of 16-01-2020.
[no-wpt-sync]
r? @servo-wpt-sync
This commit is contained in:
bors-servo 2020-01-16 07:18:08 -05:00 committed by GitHub
commit a23e2dbe48
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3570 changed files with 12529 additions and 11891 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
[keyframes-remove-documentElement-crash.html]
expected: TIMEOUT

View file

@ -1,2 +1,2 @@
[no-transition-from-ua-to-blocking-stylesheet.html]
expected: FAIL
expected: TIMEOUT

View file

@ -0,0 +1,4 @@
[CaretPosition-001.html]
[Element at (400, 100)]
expected: FAIL

View file

@ -312,24 +312,21 @@
[fetch(): separate response Content-Type: text/plain ]
expected: NOTRUN
[<iframe>: separate response Content-Type: text/plain */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;" \\" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: */* text/html]
expected: FAIL
[<iframe>: combined response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/html */*;charset=gbk]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
expected: FAIL
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
expected: FAIL

View file

@ -53,6 +53,3 @@
[combined text/javascript ]
expected: FAIL
[separate text/javascript x/x]
expected: FAIL

View file

@ -14,6 +14,3 @@
[X-Content-Type-Options%3A%20%40%23%24%23%25%25%26%5E%26%5E*()()11!%2Cnosniff]
expected: FAIL
[X-Content-Type-Options%3A%20%22nosniFF%22]
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

@ -1,6 +1,5 @@
[iframe_sandbox_popups_escaping-3.html]
type: testharness
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT
expected: FAIL

View file

@ -429,3 +429,15 @@
[onwebkittransitionend: the default value must be null]
expected: FAIL
[onwebkittransitionend: the content attribute must execute when an event is dispatched]
expected: FAIL
[onwebkitanimationstart: the content attribute must execute when an event is dispatched]
expected: FAIL
[onwebkitanimationend: the content attribute must execute when an event is dispatched]
expected: FAIL
[onwebkitanimationiteration: the content attribute must execute when an event is dispatched]
expected: FAIL

View file

@ -10,3 +10,6 @@
[Verifies the resolution of entry.startTime is at least 20 microseconds.]
expected: TIMEOUT
[Verifies the resolution of performance.now() is at least 5 microseconds.]
expected: FAIL

View file

@ -22,7 +22,7 @@ const run_test = test => {
}, test.name + " precondition: Test that the browser does not have client " +
"hints preferences cached");
// Then, attempt to set Accept-CH-Lifetime for 1 second
// Then, attempt to set Accept-CH
promise_test(t => {
return new Promise(resolve => {
if (test.type == "navigation") {

View file

@ -1,3 +1,2 @@
Accept-CH: device-memory, DPR
Accept-CH-Lifetime: 1
Access-Control-Allow-Origin: *

View file

@ -261,9 +261,8 @@ def generate_test_source_files(spec_directory, spec_json, target):
expand_pattern(excluded_pattern, test_expansion_schema)
for excluded_selection in permute_expansion(excluded_expansion,
artifact_order):
excluded_selection_path = spec_json[
'selection_pattern'] % excluded_selection
exclusion_dict[excluded_selection_path] = True
excluded_selection['delivery_key'] = spec_json['delivery_key']
exclusion_dict[dump_test_parameters(excluded_selection)] = True
for spec in specification:
# Used to make entries with expansion="override" override preceding
@ -276,20 +275,20 @@ def generate_test_source_files(spec_directory, spec_json, target):
for selection in permute_expansion(expansion, artifact_order):
selection['delivery_key'] = spec_json['delivery_key']
selection_path = spec_json['selection_pattern'] % selection
if not selection_path in exclusion_dict:
if selection_path in output_dict:
if expansion_pattern['expansion'] != 'override':
print(
"Error: %s's expansion is default but overrides %s"
% (selection['name'],
output_dict[selection_path]['name']))
sys.exit(1)
output_dict[selection_path] = copy.deepcopy(selection)
else:
print('Excluding selection:', selection_path)
if selection_path in output_dict:
if expansion_pattern['expansion'] != 'override':
print(
"Error: %s's expansion is default but overrides %s"
% (selection['name'],
output_dict[selection_path]['name']))
sys.exit(1)
output_dict[selection_path] = copy.deepcopy(selection)
for selection_path in output_dict:
selection = output_dict[selection_path]
if dump_test_parameters(selection) in exclusion_dict:
print('Excluding selection:', selection_path)
continue
try:
generate_selection(spec_directory, spec_json, selection, spec,
html_template)

View file

@ -1,6 +1,7 @@
from __future__ import print_function
import os, sys, json, re
import collections
script_directory = os.path.dirname(os.path.abspath(__file__))
template_directory = os.path.abspath(
@ -30,7 +31,7 @@ def load_spec_json(path_to_spec):
re_error_location = re.compile('line ([0-9]+) column ([0-9]+)')
with open(path_to_spec, "r") as f:
try:
return json.load(f)
return json.load(f, object_pairs_hook=collections.OrderedDict)
except ValueError as ex:
print(ex.message)
match = re_error_location.search(ex.message)

View file

@ -47,7 +47,7 @@
// is to wait for some reasonable amount of time and if no report has been
// received to conclude that no report has been generated. These timeouts must
// not exceed the test timeouts set by vendors otherwise the test would fail.
var timeout = document.querySelector("meta[name=timeout][content=long]") ? 25 : 5;
var timeout = document.querySelector("meta[name=timeout][content=long]") ? 20 : 3;
var reportLocation = location.protocol + "//" + location.host + "/content-security-policy/support/report.py?op=retrieve_report&timeout=" + timeout + "&reportID=" + reportID;
if (testName == "") testName = "Violation report status OK.";

View file

@ -1,8 +1,7 @@
<!doctype html>
<html class="test-wait">
<title>CSS Animations Test: Chrome crash when removing documentElement and @keyframes stylesheet</title>
<link rel="help" href="https://crbug.com/999522">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
@keyframes anim {
from { color: pink }
@ -14,9 +13,16 @@
</style>
<div></div>
<script>
test(() => {
document.body.offsetTop;
document.querySelector("style").remove();
document.documentElement.remove();
}, "Removing documentElement and @keyframes sheet should not crash.");
window.addEventListener('load', () => {
document.body.offsetTop;
document.querySelector("style").remove();
// We need the root later to remove the test-wait class.
const root = document.documentElement;
document.documentElement.remove();
// rAF to make sure that style runs.
requestAnimationFrame(() => {
root.classList.remove('test-wait');
});
});
</script>

View file

@ -0,0 +1,83 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Pseudo-Elements Test: Computed size of ::marker</title>
<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
<link rel="help" href="https://drafts.csswg.org/css-lists/#content-property">
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
<meta name="assert" content="This test checks that getComputedStyle exposes the resolved sizes of a ::marker." />
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
<style>
:root {
--image: url('/images/green-100x50.png');
}
:root::after {
/* Preload image */
content: var(--image);
}
#target {
font: 10px/1 Ahem;
--content: normal;
}
#target::marker {
content: var(--content);
}
</style>
<div id="log"></div>
<ul>
<li id="target"></li>
</ul>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const target = document.getElementById("target");
function checkMarkerSize(expectedWidth, expectedHeight) {
const {width, height} = getComputedStyle(target, "::marker");
assert_equals(width, expectedWidth, "width");
assert_equals(height, expectedHeight, "height");
}
setup({explicit_done: true});
addEventListener("load", () => {
test(() => {
// Marker string: "1. "
target.style.listStyleType = "decimal";
checkMarkerSize("30px", "10px");
}, "Decimal ::marker");
test(() => {
// Marker string: "10. "
target.setAttribute("value", "10");
checkMarkerSize("40px", "10px");
}, "Decimal ::marker with custom value");
test(() => {
// Marker string: "st"
target.style.listStyleType = "'st'";
checkMarkerSize("20px", "10px");
}, "String ::marker");
test(() => {
// No marker box
target.style.listStyleType = "none";
checkMarkerSize("auto", "auto");
}, "::marker with no box due to 'list-style'");
test(() => {
// Marker contents: "foo", "bar"
target.style.setProperty("--content", "'foo' 'bar'");
checkMarkerSize("60px", "10px");
}, "::marker with custom string contents");
test(() => {
// Marker contents: 100x50 image (+2px due to baseline alignment)
target.style.setProperty("--content", "var(--image)");
checkMarkerSize("100px", "52px");
}, "::marker with custom image contents");
test(() => {
// Marker contents: "foo", 100x50 image (+2px due to baseline alignment)
target.style.setProperty("--content", "'foo' var(--image)");
checkMarkerSize("130px", "52px");
}, "::marker with custom string and image contents");
test(() => {
// No marker box
target.style.listStyleType = "";
target.style.setProperty("--content", "none");
checkMarkerSize("auto", "auto");
}, "::marker with no box due to 'content'");
done();
}, {once: true});
</script>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>CSS Shadow Parts - Serialization</title>
<link href="https://drafts.csswg.org/css-shadow-parts/" rel="help">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<style id="styleElement">
::part(\(foo) {}
::part( bar\ ) {}
::part( -foo bar ) {}
</style>
<script>
"use strict";
const rules = styleElement.sheet.cssRules;
test(function() {
assert_equals(rules[0].selectorText, "::part(\\(foo)");
}, "Escape start parenthesis in ::part name.");
test(function() {
assert_equals(rules[1].selectorText, "::part(bar\\ )");
}, "Escape start space in ::part name.");
test(function() {
assert_equals(rules[2].selectorText, "::part(-foo bar)");
}, "Collapse spaces in ::part names list.");
</script>
</body>
</html>

View file

@ -70,6 +70,7 @@
test(function(){
assert_selector_serializes_to(':lang(ja)', ':lang(ja)');
assert_selector_serializes_to(':lang( ja )', ':lang(ja)');
assert_selector_serializes_to(':lang( j\\ a )', ':lang(j\\ a)');
}, 'single pseudo (simple) selector "lang" which accepts arguments in the sequence of simple selectors that is not a universal selector')

View file

@ -10,7 +10,7 @@
#test {
color: rgb(255, 0, 0);
}
span::-webkit-something-invalid, #test, ::-WeBkIt-sOmEtHiNg-NoNeXiSt123 {
span::-webkit-something-invalid, #test, ::-WeBkIt-sOmEtHiNg-NoNeXiSt123, ::-webkit-\ escaped {
color: rgb(0, 255, 0);
}
::-webkitfoo, #test {
@ -29,7 +29,8 @@ span::-webkit-something-invalid, #test, ::-WeBkIt-sOmEtHiNg-NoNeXiSt123 {
let sheet = document.getElementById("style").sheet;
assert_equals(sheet.cssRules[1].selectorText,
"span::-webkit-something-invalid, " +
"#test, ::-webkit-something-nonexist123");
"#test, ::-webkit-something-nonexist123, " +
"::-webkit-\\ escaped");
}, "webkit-prefixed pseudo-element selectors should be accessible from CSSOM");
test(() => {

View file

@ -12,11 +12,10 @@ The simplest crashtest is a single HTML file with any content. The
test passes if the load event is reached, and the browser finishes
painting, without terminating.
In some cases crashtests may need to perform work after the initial
page load. In this case the test may specify a `class=wait` attribute
on the root element. The test will not complete until that attribute
is removed from the root. At the time when the test would otherwise
have ended a `TestRendered` event is emitted; test authors can use
this event to perform modifications that are guaranteed not to be
batched with the initial paint. This matches the behaviour of
[reftests](reftests).
In some cases crashtests may need to perform work after the initial page load.
In this case the test may specify a `class=test-wait` attribute on the root
element. The test will not complete until that attribute is removed from the
root. At the time when the test would otherwise have ended a `TestRendered`
event is emitted; test authors can use this event to perform modifications that
are guaranteed not to be batched with the initial paint. This matches the
behaviour of [reftests](reftests).

View file

@ -28,14 +28,13 @@ const origins = get_host_info();
t.add_cleanup(() => { frame.remove(); });
const path = new URL("resources/blob-url-factory.html", window.location).pathname;
frame.src = `${origin}${path}?id=${id}&variant=${variant}&crossOrigin=${crossOrigin}`;
window.addEventListener("message", t.step_func(({ data }) => {
window.addEventListener("message", t.step_func_done(({ data }) => {
if (data.id !== id) {
return;
}
assert_equals(data.origin, origin);
assert_true(data.sameOriginNoCORPSuccess, "Same-origin without CORP did not succeed");
assert_true(data.crossOriginNoCORPFailure, "Cross-origin without CORP did not fail");
t.done();
}));
document.body.append(frame);
}, `Cross-Origin-Embedder-Policy and blob: URL from ${origin} in subframe via ${variant}`);

View file

@ -0,0 +1,39 @@
<!doctype html>
<title>Cross-Origin-Opener-Policy and a blob URL popup</title>
<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>
async_test(t => {
window.test = t; // Make the test available globally so the blob URL can use it
window.furtherPopup = null;
const bc = new BroadcastChannel(token());
bc.onmessage = t.step_func_done(({ data }) => {
assert_equals(data.name, "");
assert_false(data.opener);
assert_true(furtherPopup.closed);
assert_equals(furtherPopup.document.URL, "about:blank");
});
const blobContents = `<script>
const w = window.open("${get_host_info().HTTPS_REMOTE_ORIGIN}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=x&coep=x&channel=${bc.name}", "${bc.name}");
window.opener.furtherPopup = w;
// w will be closed by its postback iframe. When out of process,
// window.close() does not work.
window.opener.test.add_cleanup(() => w.close());
<\/script>`;
const blob = new Blob([blobContents], { type: "text/html" });
const blobURL = URL.createObjectURL(blob);
const popup = window.open(blobURL);
t.add_cleanup(() => popup.close());
popup.onload = t.step_func(() => {
assert_equals(popup.opener, window);
assert_equals(popup.location.href, blobURL);
assert_equals(popup.document.URL, blobURL);
assert_equals(popup.origin, window.origin);
});
});
</script>

View file

@ -0,0 +1 @@
Cross-Origin-Opener-Policy: same-origin

View file

@ -0,0 +1,45 @@
<!doctype html>
<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: blob URL popup</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/common/get-host-info.sub.js></script>
<script src=../cross-origin-embedder-policy/resources/script-factory.js></script>
<script>
["window.open()", "<a>", "<a rel=noopener>"].forEach(type => {
promise_test(t => {
const origins = get_host_info();
const id = `tut mir leid ${type}`;
const blob = new Blob([createScript(origins.ORIGIN, origins.HTTPS_REMOTE_ORIGIN, "opener", id)], {type: "text/html"});
const blobURL = URL.createObjectURL(blob);
if (type === "window.open()") {
const popup = window.open(blobURL);
t.add_cleanup(() => popup.close());
popup.onload = t.step_func(() => {
assert_equals(popup.opener, window);
assert_equals(popup.location.href, blobURL);
assert_equals(popup.document.URL, blobURL);
assert_equals(popup.origin, window.origin);
});
} else {
const a = document.createElement("a");
a.target = type;
if (type === "<a rel=noopener>") {
a.rel = "noopener";
}
a.href = blobURL;
a.click();
}
return new Promise(resolve => {
window.addEventListener("message", t.step_func(({ data }) => {
assert_equals(data.id, id);
assert_equals(data.origin, window.origin);
assert_true(data.sameOriginNoCORPSuccess, "Same-origin without CORP did not succeed");
assert_true(data.crossOriginNoCORPFailure, "Cross-origin without CORP did not fail");
resolve();
}));
});
}, `COOP+COEP blob URL popup: ${type}`);
});
</script>

View file

@ -0,0 +1,2 @@
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

View file

@ -0,0 +1,43 @@
<!doctype html>
<meta charset=utf-8>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/common.js"></script>
<div id=log></div>
<script>
[
[SAME_ORIGIN, SAME_ORIGIN, "same-origin", false, false],
[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],
[SAME_ORIGIN, SAME_ORIGIN, "same-origin-allow-popups", true, true],
[SAME_SITE, SAME_ORIGIN, "same-origin-allow-popups", false, false],
[CROSS_ORIGIN, SAME_ORIGIN, "same-origin-allow-popups", false, false],
[SAME_ORIGIN, SAME_SITE, "same-origin-allow-popups", false, false],
[SAME_SITE, SAME_SITE, "same-origin-allow-popups", false, false],
[CROSS_ORIGIN, SAME_SITE, "same-origin-allow-popups", false, false],
[SAME_ORIGIN, CROSS_ORIGIN, "same-origin-allow-popups", false, false],
[SAME_SITE, CROSS_ORIGIN, "same-origin-allow-popups", false, false],
[CROSS_ORIGIN, CROSS_ORIGIN, "same-origin-allow-popups", false, false],
[SAME_ORIGIN, SAME_ORIGIN, "", true, true],
[SAME_SITE, SAME_ORIGIN, "", true, true],
[CROSS_ORIGIN, SAME_ORIGIN, "", true, true],
[SAME_ORIGIN, SAME_SITE, "", true, true],
[SAME_SITE, SAME_SITE, "", true, true],
[CROSS_ORIGIN, SAME_SITE, "", true, true],
[SAME_ORIGIN, CROSS_ORIGIN, "", true, true],
[SAME_SITE, CROSS_ORIGIN, "", true, true],
[CROSS_ORIGIN, CROSS_ORIGIN, "", true, true],
].forEach( value => {
run_coop_test_iframe("same-origin-allow-popups", value[0], value[1], value[2], value[3], value[4]);
});
</script>

View file

@ -0,0 +1 @@
Cross-Origin-Opener-Policy: same-origin-allow-popups

View file

@ -0,0 +1,33 @@
<!doctype html>
<meta charset=utf-8>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/common.js"></script>
<div id=log></div>
<script>
[
[SAME_ORIGIN, SAME_ORIGIN, "same-origin", true, true],
[SAME_SITE, SAME_ORIGIN, "same-origin", false, true],
[CROSS_ORIGIN, SAME_ORIGIN, "same-origin", false, true],
[SAME_ORIGIN, SAME_SITE, "same-origin", false, false],
[SAME_SITE, SAME_SITE, "same-origin", false, true],
[CROSS_ORIGIN, SAME_SITE, "same-origin", false, true],
[SAME_ORIGIN, CROSS_ORIGIN, "same-origin", false, false],
[SAME_SITE, CROSS_ORIGIN, "same-origin", false, true],
[CROSS_ORIGIN, CROSS_ORIGIN, "same-origin", false, true],
[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]);
});
</script>

View file

@ -0,0 +1 @@
Cross-Origin-Opener-Policy: same-origin

View file

@ -0,0 +1,33 @@
<!doctype html>
<meta charset=utf-8>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/common.js"></script>
<div id=log></div>
<script>
[
[SAME_ORIGIN, SAME_ORIGIN, "same-origin", false, false],
[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],
[SAME_ORIGIN, SAME_ORIGIN, "", true, true],
[SAME_SITE, SAME_ORIGIN, "", true, true],
[CROSS_ORIGIN, SAME_ORIGIN, "", true, true],
[SAME_ORIGIN, SAME_SITE, "", true, true],
[SAME_SITE, SAME_SITE, "", true, true],
[CROSS_ORIGIN, SAME_SITE, "", true, true],
[SAME_ORIGIN, CROSS_ORIGIN, "", true, true],
[SAME_SITE, CROSS_ORIGIN, "", true, true],
[CROSS_ORIGIN, CROSS_ORIGIN, "", true, true],
].forEach( value => {
run_coop_test_iframe("unsafe-none", value[0], value[1], value[2], value[3], value[4]);
});
</script>

View file

@ -0,0 +1 @@
Cross-Origin-Opener-Policy: unsafe-none

View file

@ -38,3 +38,23 @@ function run_coop_tests(documentCOOPValueTitle, testArray) {
}, `${documentCOOPValueTitle} document opening popup to ${test[0].origin} with COOP: "${test[1]}"`);
}
}
function run_coop_test_iframe (documentTitle, iframe_origin, popup_origin, popup_coop, expects_opener, expects_name) {
const name = iframe_origin.name + "_iframe_opening_" + popup_origin.name + "_popup_with_coop_" + popup_coop;
async_test(t => {
const frame = document.createElement("iframe");
t.add_cleanup(() => { frame.remove(); });
const origin = CROSS_ORIGIN.origin;
const path = new URL("resources/iframe-popup.sub.html", window.location).pathname;
const bc = new BroadcastChannel(name);
frame.src = `${iframe_origin.origin}${path}?popup_origin=${popup_origin.origin}&popup_coop=${popup_coop}&channel=${name}`;
bc.onmessage = t.step_func_done(event => {
const payload = event.data;
assert_equals(payload.opener, expects_opener, 'opener');
assert_equals(payload.name, expects_name? name:"", 'name');
});
document.body.append(frame);
}, `${documentTitle} with ${iframe_origin.name} iframe opening popup a ${popup_origin.name} with COOP: ${popup_coop}`);
}

View file

@ -0,0 +1,11 @@
<!doctype html>
<meta charset=utf-8>
<script>
const popup_origin = new URL(location).searchParams.get("popup_origin");
const channelName = new URL(location).searchParams.get("channel");
const popup_coop = new URL(location).searchParams.get("popup_coop");
const url = `${popup_origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=${encodeURIComponent(popup_coop)}&coep=&channel=${channelName}`;
window.open(url, channelName);
</script>

View file

@ -10,6 +10,16 @@
<script>
"use strict";
// The prefixed animation events are special; their event types are
// camel-case.
const prefixedAnimationAttributeToEventType = new Map([
["webkitanimationend", "webkitAnimationEnd"],
["webkitanimationiteration", "webkitAnimationIteration"],
["webkitanimationstart", "webkitAnimationStart"],
["webkittransitionend", "webkitTransitionEnd"],
]);
setup({ explicit_done: true });
fetch("/interfaces/html.idl").then(res => res.text()).then(htmlIDL => {
@ -54,7 +64,11 @@ fetch("/interfaces/html.idl").then(res => res.text()).then(htmlIDL => {
const el = document.createElement("div");
el.setAttribute(name, `window.${name}Happened2 = true;`);
el.dispatchEvent(new Event(withoutOn));
let eventType = withoutOn;
if (prefixedAnimationAttributeToEventType.has(eventType)) {
eventType = prefixedAnimationAttributeToEventType.get(eventType);
}
el.dispatchEvent(new Event(eventType));
assert_true(window[name + "Happened2"], "Dispatching an event must run the code");
}, `${name}: the content attribute must execute when an event is dispatched`);

View file

@ -6,7 +6,12 @@ tests for the reference JavaScript implementation at [WICG repository](https://g
## Basics
A **test object** describes a set of parameters (import maps and base URLs) and specifiers to be tested.
A **test object** describes a set of parameters (import maps and base URLs) and test expectations.
Test expectations can be:
- Expected resulting URLs for specifiers (resolution tests), or
- Expected parsed import maps (parsing tests).
Each JSON file under [resources/](resources/) directory consists of a test object.
A minimum test object would be:
@ -33,10 +38,11 @@ Required fields:
- In WPT tests, this is used for the test name of `promise_test()` together with specifier to be resolved, like `"Main test name: a"`.
- `importMap` (object or string): the import map to be attached.
- `importMapBaseURL` (string): the base URL used for [parsing the import map](https://wicg.github.io/import-maps/#parse-an-import-map-string).
- `baseURL` (string): the base URL used in [resolving a specifier](https://wicg.github.io/import-maps/#resolve-a-module-specifier) for each specifiers.
- `expectedResults` (object; string to (string or null)): test cases.
- (resolution tests only) `expectedResults` (object; string to (string or null)): resolution test cases.
- The keys are specifiers to be resolved.
- The values are expected resolved URLs. If `null`, resolution should fail.
- (resolution tests only) `baseURL` (string): the base URL used in [resolving a specifier](https://wicg.github.io/import-maps/#resolve-a-module-specifier) for each specifiers.
- (parsing tests only) `expectedParsedImportMap` (object): the expected parsed import map for parsing test cases.
Optional fields:

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script type="module">
import { runTestsFromJSON } from "./resources/common-test-helper.js";
for (const json of [
'resources/parsing-addresses-absolute.json',
'resources/parsing-addresses-invalid.json',
'resources/parsing-addresses.json',
'resources/parsing-invalid-json.json',
'resources/parsing-schema-normalization.json',
'resources/parsing-schema-scope.json',
'resources/parsing-schema-specifier-map.json',
'resources/parsing-schema-toplevel.json',
'resources/parsing-scope-keys.json',
'resources/parsing-specifier-keys.json',
'resources/parsing-trailing-slashes.json',
]) {
promise_test(() =>
runTestsFromJSON(json),
"Test helper: fetching and sanity checking test JSON: " + json);
}
</script>

View file

@ -2,17 +2,15 @@ setup({allow_uncaught_exception : true});
// Creates a new Document (via <iframe>) and add an inline import map.
function parse(importMap, importMapBaseURL) {
return new Promise((resolve, reject) => {
return new Promise(resolve => {
const importMapString = JSON.stringify(importMap);
const iframe = document.createElement('iframe');
window.addEventListener('message', event => {
if (event.data.type === 'Success') {
resolve(iframe);
} else {
// Currently we don't distinguish fetch errors and parse errors.
reject(event.data.error);
}
// Parsing result is saved here and checked later, rather than
// rejecting the promise on errors.
iframe.parseImportMapResult = event.data.type;
resolve(iframe);
},
{once: true});
@ -40,18 +38,28 @@ function parse(importMap, importMapBaseURL) {
// Handle specifier resolution requests from the parent frame.
window.addEventListener('message', event => {
try {
// URL resolution is tested using Chromium's internals.
// TODO(hiroshige): Remove the Chromium-specific dependency.
const result = internals.resolveModuleSpecifier(
event.data.specifier,
event.data.baseURL,
document);
parent.postMessage({type: 'ResolutionSuccess', result: result}, '*');
if (event.data.action === 'resolve') {
// URL resolution is tested using Chromium's internals.
// TODO(hiroshige): Remove the Chromium-specific dependency.
const result = internals.resolveModuleSpecifier(
event.data.specifier,
event.data.baseURL,
document);
parent.postMessage({type: 'ResolutionSuccess', result: result}, '*');
} else if (event.data.action === 'getParsedImportMap') {
parent.postMessage({
type: 'GetParsedImportMapSuccess',
result: internals.getParsedImportMap(document)}, '*');
} else {
parent.postMessage({
type: 'Failure',
result: "Invalid Action: " + event.data.action}, '*');
}
} catch (e) {
// We post error names instead of error objects themselves and
// re-create error objects later, to avoid issues around serializing
// error objects which is a quite new feature.
parent.postMessage({type: 'ResolutionFailure', result: e.name}, '*');
parent.postMessage({type: 'Failure', result: e.name}, '*');
}
});
</script>
@ -77,7 +85,7 @@ function resolve(specifier, parsedImportMap, baseURL) {
window.addEventListener('message', event => {
if (event.data.type === 'ResolutionSuccess') {
resolve(event.data.result);
} else if (event.data.type === 'ResolutionFailure') {
} else if (event.data.type === 'Failure') {
if (event.data.result === 'TypeError') {
reject(new TypeError());
} else {
@ -90,7 +98,21 @@ function resolve(specifier, parsedImportMap, baseURL) {
{once: true});
parsedImportMap.contentWindow.postMessage(
{specifier: specifier, baseURL: baseURL}, '*');
{action: "resolve", specifier: specifier, baseURL: baseURL}, '*');
});
}
// Returns a promise that is resolved with a serialized string of
// a parsed import map JSON object.
function getParsedImportMap(parsedImportMap) {
return new Promise((resolve, reject) => {
window.addEventListener('message', event => {
resolve(event.data.result);
},
{once: true});
parsedImportMap.contentWindow.postMessage(
{action: "getParsedImportMap"}, '*');
});
}
@ -101,11 +123,27 @@ function assert_no_extra_properties(object, expectedProperties, description) {
}
}
// 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());
}
async function runTests(j) {
const tests = j.tests;
delete j.tests;
if (j.importMap) {
if (j.hasOwnProperty('importMap')) {
assert_own_property(j, 'importMap');
assert_own_property(j, 'importMapBaseURL');
j.parsedImportMap = await parse(j.importMap, j.importMapBaseURL);
@ -115,7 +153,8 @@ async function runTests(j) {
assert_no_extra_properties(
j,
['expectedResults', 'baseURL', 'name', 'parsedImportMap',
['expectedResults', 'expectedParsedImportMap',
'baseURL', 'name', 'parsedImportMap',
'importMap', 'importMapBaseURL',
'link', 'details'],
j.name);
@ -133,26 +172,51 @@ async function runTests(j) {
}
} else {
// Leaf node.
for (const key of
['expectedResults', 'parsedImportMap', 'baseURL', 'name']) {
for (const key of ['parsedImportMap', 'name']) {
assert_own_property(j, key, j.name);
}
assert_true(j.hasOwnProperty('expectedResults') ||
j.hasOwnProperty('expectedParsedImportMap'),
'expectedResults or expectedParsedImportMap should exist');
for (const specifier in j.expectedResults) {
const expected = j.expectedResults[specifier];
promise_test(async t => {
if (expected === null) {
return promise_rejects(t, new TypeError(),
resolve(specifier, j.parsedImportMap, j.baseURL));
} else {
// Should be resolved to `expected`.
const actual = await resolve(
specifier, j.parsedImportMap, j.baseURL);
assert_equals(actual, expected);
}
},
j.name + ': ' + specifier);
// Resolution tests.
if (j.hasOwnProperty('expectedResults')) {
assert_own_property(j, 'baseURL');
assert_equals(
j.parsedImportMap.parseImportMapResult,
"Success",
"Import map registration should be successful for resolution tests");
for (const specifier in j.expectedResults) {
const expected = j.expectedResults[specifier];
promise_test(async t => {
if (expected === null) {
return promise_rejects(t, new TypeError(),
resolve(specifier, j.parsedImportMap, j.baseURL));
} else {
// Should be resolved to `expected`.
const actual = await resolve(
specifier, j.parsedImportMap, j.baseURL);
assert_equals(actual, expected);
}
},
j.name + ': ' + specifier);
}
}
// Parsing tests.
if (j.hasOwnProperty('expectedParsedImportMap')) {
promise_test(async t => {
if (j.expectedParsedImportMap === null) {
assert_equals(j.parsedImportMap.parseImportMapResult, "ParseError");
} else {
const actualParsedImportMap =
await getParsedImportMap(j.parsedImportMap);
assert_equals(stringifyImportMap(JSON.parse(actualParsedImportMap)),
stringifyImportMap(j.expectedParsedImportMap));
}
}, j.name);
}
}
}

View file

@ -0,0 +1,63 @@
{
"name": "Absolute URL addresses",
"tests": {
"should only accept absolute URL addresses with fetch schemes": {
"importMap": {
"imports": {
"about": "about:good",
"blob": "blob:good",
"data": "data:good",
"file": "file:///good",
"filesystem": "filesystem:http://example.com/good/",
"http": "http://good/",
"https": "https://good/",
"ftp": "ftp://good/",
"import": "import:bad",
"mailto": "mailto:bad",
"javascript": "javascript:bad",
"wss": "wss:bad"
}
},
"importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": {
"imports": {
"about": "about:good",
"blob": "blob:good",
"data": "data:good",
"file": "file:///good",
"filesystem": "filesystem:http://example.com/good/",
"http": "http://good/",
"https": "https://good/",
"ftp": "ftp://good/",
"import": "import:bad",
"javascript": "javascript:bad",
"mailto": "mailto:bad",
"wss": "wss://bad/"
},
"scopes": {}
}
},
"should parse absolute URLs, ignoring unparseable ones": {
"importMap": {
"imports": {
"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/"
}
},
"importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": {
"imports": {
"invalidButParseable1": "https://example.org/",
"invalidButParseable2": "https://example.com///",
"prettyNormal": "https://example.net/",
"percentDecoding": "https://example.com/"
},
"scopes": {}
}
}
}
}

View file

@ -0,0 +1,21 @@
{
"name": "Other invalid addresses",
"tests": {
"should ignore unprefixed strings that are not absolute URLs": {
"importMap": {
"imports": {
"foo1": "bar",
"foo2": "\\bar",
"foo3": "~bar",
"foo4": "#bar",
"foo5": "?bar"
}
},
"importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
}
}
}

View file

@ -0,0 +1,73 @@
{
"name": "Relative URL-like addresses",
"tests": {
"should accept strings prefixed with ./, ../, or /": {
"importMap": {
"imports": {
"dotSlash": "./foo",
"dotDotSlash": "../foo",
"slash": "/foo"
}
},
"importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": {
"imports": {
"dotSlash": "https://base.example/path1/path2/foo",
"dotDotSlash": "https://base.example/path1/foo",
"slash": "https://base.example/foo"
},
"scopes": {}
}
},
"should not accept strings prefixed with ./, ../, or / for data: base URLs": {
"importMap": {
"imports": {
"dotSlash": "./foo",
"dotDotSlash": "../foo",
"slash": "/foo"
}
},
"importMapBaseURL": "data:text/html,test",
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
},
"should accept the literal strings ./, ../, or / with no suffix": {
"importMap": {
"imports": {
"dotSlash": "./",
"dotDotSlash": "../",
"slash": "/"
}
},
"importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": {
"imports": {
"dotSlash": "https://base.example/path1/path2/",
"dotDotSlash": "https://base.example/path1/",
"slash": "https://base.example/"
},
"scopes": {}
}
},
"should ignore percent-encoded variants of ./, ../, or /": {
"importMap": {
"imports": {
"dotSlash1": "%2E/",
"dotDotSlash1": "%2E%2E/",
"dotSlash2": ".%2F",
"dotDotSlash2": "..%2F",
"slash2": "%2F",
"dotSlash3": "%2E%2F",
"dotDotSlash3": "%2E%2E%2F"
}
},
"importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
}
}
}

View file

@ -0,0 +1,6 @@
{
"name": "Invalid JSON",
"importMapBaseURL": "https://base.example/",
"importMap": "{imports: {}}",
"expectedParsedImportMap": null
}

View file

@ -0,0 +1,31 @@
{
"name": "Normalization",
"importMapBaseURL": "https://base.example/",
"tests": {
"should normalize empty import maps to have imports and scopes keys": {
"importMap": {},
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
},
"should normalize an import map without imports to have imports": {
"importMap": {
"scopes": {}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
},
"should normalize an import map without scopes to have scopes": {
"importMap": {
"imports": {}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
}
}
}

View file

@ -0,0 +1,46 @@
{
"name": "Mismatching scopes schema",
"importMapBaseURL": "https://base.example/",
"tests": {
"should throw if a scope's value is not an object": {
"expectedParsedImportMap": null,
"tests": {
"null": {
"importMap": {
"scopes": {
"https://example.com/": null
}
}
},
"boolean": {
"importMap": {
"scopes": {
"https://example.com/": true
}
}
},
"number": {
"importMap": {
"scopes": {
"https://example.com/": 1
}
}
},
"string": {
"importMap": {
"scopes": {
"https://example.com/": "foo"
}
}
},
"array": {
"importMap": {
"scopes": {
"https://example.com/": []
}
}
}
}
}
}
}

View file

@ -0,0 +1,38 @@
{
"name": "Mismatching the specifier map schema",
"importMapBaseURL": "https://base.example/",
"tests": {
"should ignore entries where the address is not a string": {
"importMap": {
"imports": {
"null": null,
"boolean": true,
"number": 1,
"object": {},
"array": [],
"array2": [
"https://example.com/"
],
"string": "https://example.com/"
}
},
"expectedParsedImportMap": {
"imports": {
"string": "https://example.com/"
},
"scopes": {}
}
},
"should ignore entries where the specifier key is an empty string": {
"importMap": {
"imports": {
"": "https://example.com/"
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
}
}
}

View file

@ -0,0 +1,97 @@
{
"name": "Mismatching the top-level schema",
"importMapBaseURL": "https://base.example/",
"tests": {
"should throw for top-level non-objects": {
"expectedParsedImportMap": null,
"tests": {
"null": {
"importMap": null
},
"boolean": {
"importMap": true
},
"number": {
"importMap": 1
},
"string": {
"importMap": "foo"
},
"array": {
"importMap": []
}
}
},
"should throw if imports is a non-object": {
"expectedParsedImportMap": null,
"tests": {
"null": {
"importMap": {
"imports": null
}
},
"boolean": {
"importMap": {
"imports": true
}
},
"number": {
"importMap": {
"imports": 1
}
},
"string": {
"importMap": {
"imports": "foo"
}
},
"array": {
"importMap": {
"imports": []
}
}
}
},
"should throw if scopes is a non-object": {
"expectedParsedImportMap": null,
"tests": {
"null": {
"importMap": {
"scopes": null
}
},
"boolean": {
"importMap": {
"scopes": true
}
},
"number": {
"importMap": {
"scopes": 1
}
},
"string": {
"importMap": {
"scopes": "foo"
}
},
"array": {
"importMap": {
"scopes": []
}
}
}
},
"should ignore unspecified top-level entries": {
"importMap": {
"imports": {},
"new-feature": {},
"scops": {}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
}
}
}

View file

@ -0,0 +1,191 @@
{
"importMapBaseURL": "https://base.example/path1/path2/path3",
"tests": {
"Relative URL scope keys should work with no prefix": {
"importMap": {
"scopes": {
"foo": {}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"https://base.example/path1/path2/foo": {}
}
}
},
"Relative URL scope keys should work with ./, ../, and / prefixes": {
"importMap": {
"scopes": {
"./foo": {},
"../foo": {},
"/foo": {}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"https://base.example/path1/path2/foo": {},
"https://base.example/path1/foo": {},
"https://base.example/foo": {}
}
}
},
"Absolute URL scope keys should ignore relative URL scope keys when the base URL is a data: URL": {
"importMap": {
"scopes": {
"./foo": {},
"../foo": {},
"/foo": {}
}
},
"importMapBaseURL": "data:text/html,test",
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
},
"Relative URL scope keys should work with ./, ../, or / with no suffix": {
"importMap": {
"scopes": {
"./": {},
"../": {},
"/": {}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"https://base.example/path1/path2/": {},
"https://base.example/path1/": {},
"https://base.example/": {}
}
}
},
"Relative URL scope keys should work with /s, ?s, and #s": {
"importMap": {
"scopes": {
"foo/bar?baz#qux": {}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"https://base.example/path1/path2/foo/bar?baz#qux": {}
}
}
},
"Relative URL scope keys should work with an empty string scope key": {
"importMap": {
"scopes": {
"": {}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"https://base.example/path1/path2/path3": {}
}
}
},
"Relative URL scope keys should work with / suffixes": {
"importMap": {
"scopes": {
"foo/": {},
"./foo/": {},
"../foo/": {},
"/foo/": {},
"/foo//": {}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"https://base.example/path1/path2/foo/": {},
"https://base.example/path1/foo/": {},
"https://base.example/foo/": {},
"https://base.example/foo//": {}
}
}
},
"Relative URL scope keys should deduplicate based on URL parsing rules": {
"importMap": {
"scopes": {
"foo/\\": {
"1": "./a"
},
"foo//": {
"2": "./b"
},
"foo\\\\": {
"3": "./c"
}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"https://base.example/path1/path2/foo//": {
"3": "https://base.example/path1/path2/c"
}
}
}
},
"Absolute URL scope keys should accept all absolute URL scope keys, with or without fetch schemes": {
"importMap": {
"scopes": {
"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": {}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"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/": {}
}
}
},
"Absolute URL scope keys should parse absolute URL scope keys, ignoring unparseable ones": {
"importMap": {
"scopes": {
"https://example.com:demo": {},
"http://[www.example.com]/": {},
"https:example.org": {},
"https://///example.com///": {},
"https://example.net": {},
"https://ex%41mple.com/foo/": {}
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {
"https://base.example/path1/path2/example.org": {},
"https://example.com///": {},
"https://example.net/": {},
"https://example.com/foo/": {}
}
}
}
}
}

View file

@ -0,0 +1,209 @@
{
"importMapBaseURL": "https://base.example/path1/path2/path3",
"tests": {
"Relative URL specifier keys should absolutize strings prefixed with ./, ../, or / into the corresponding URLs": {
"importMap": {
"imports": {
"./foo": "/dotslash",
"../foo": "/dotdotslash",
"/foo": "/slash"
}
},
"expectedParsedImportMap": {
"imports": {
"https://base.example/path1/path2/foo": "https://base.example/dotslash",
"https://base.example/path1/foo": "https://base.example/dotdotslash",
"https://base.example/foo": "https://base.example/slash"
},
"scopes": {}
}
},
"Relative URL specifier keys should not absolutize strings prefixed with ./, ../, or / with a data: URL base": {
"importMap": {
"imports": {
"./foo": "https://example.com/dotslash",
"../foo": "https://example.com/dotdotslash",
"/foo": "https://example.com/slash"
}
},
"importMapBaseURL": "data:text/html,",
"expectedParsedImportMap": {
"imports": {
"./foo": "https://example.com/dotslash",
"../foo": "https://example.com/dotdotslash",
"/foo": "https://example.com/slash"
},
"scopes": {}
}
},
"Relative URL specifier keys should absolutize the literal strings ./, ../, or / with no suffix": {
"importMap": {
"imports": {
"./": "/dotslash/",
"../": "/dotdotslash/",
"/": "/slash/"
}
},
"expectedParsedImportMap": {
"imports": {
"https://base.example/path1/path2/": "https://base.example/dotslash/",
"https://base.example/path1/": "https://base.example/dotdotslash/",
"https://base.example/": "https://base.example/slash/"
},
"scopes": {}
}
},
"Relative URL specifier keys should work with /s, ?s, and #s": {
"importMap": {
"imports": {
"./foo/bar?baz#qux": "/foo"
}
},
"expectedParsedImportMap": {
"imports": {
"https://base.example/path1/path2/foo/bar?baz#qux": "https://base.example/foo"
},
"scopes": {}
}
},
"Relative URL specifier keys should ignore an empty string key": {
"importMap": {
"imports": {
"": "/foo"
}
},
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
},
"Relative URL specifier keys should treat percent-encoded variants of ./, ../, or / as bare specifiers": {
"importMap": {
"imports": {
"%2E/": "/dotSlash1/",
"%2E%2E/": "/dotDotSlash1/",
".%2F": "/dotSlash2",
"..%2F": "/dotDotSlash2",
"%2F": "/slash2",
"%2E%2F": "/dotSlash3",
"%2E%2E%2F": "/dotDotSlash3"
}
},
"expectedParsedImportMap": {
"imports": {
"%2E/": "https://base.example/dotSlash1/",
"%2E%2E/": "https://base.example/dotDotSlash1/",
".%2F": "https://base.example/dotSlash2",
"..%2F": "https://base.example/dotDotSlash2",
"%2F": "https://base.example/slash2",
"%2E%2F": "https://base.example/dotSlash3",
"%2E%2E%2F": "https://base.example/dotDotSlash3"
},
"scopes": {}
}
},
"Relative URL specifier keys should deduplicate based on URL parsing rules": {
"importMap": {
"imports": {
"./foo/\\": "/foo1",
"./foo//": "/foo2",
"./foo\\\\": "/foo3"
}
},
"expectedParsedImportMap": {
"imports": {
"https://base.example/path1/path2/foo//": "https://base.example/foo3"
},
"scopes": {}
}
},
"Absolute URL specifier keys should accept all absolute URL specifier keys, with or without fetch schemes": {
"importMap": {
"imports": {
"about:good": "/about",
"blob:good": "/blob",
"data:good": "/data",
"file:///good": "/file",
"filesystem:http://example.com/good/": "/filesystem/",
"http://good/": "/http/",
"https://good/": "/https/",
"ftp://good/": "/ftp/",
"import:bad": "/import",
"mailto:bad": "/mailto",
"javascript:bad": "/javascript",
"wss:bad": "/wss"
}
},
"expectedParsedImportMap": {
"imports": {
"about:good": "https://base.example/about",
"blob:good": "https://base.example/blob",
"data:good": "https://base.example/data",
"file:///good": "https://base.example/file",
"filesystem:http://example.com/good/": "https://base.example/filesystem/",
"http://good/": "https://base.example/http/",
"https://good/": "https://base.example/https/",
"ftp://good/": "https://base.example/ftp/",
"import:bad": "https://base.example/import",
"mailto:bad": "https://base.example/mailto",
"javascript:bad": "https://base.example/javascript",
"wss://bad/": "https://base.example/wss"
},
"scopes": {}
}
},
"Absolute URL specifier keys should parse absolute URLs, treating unparseable ones as bare specifiers": {
"importMap": {
"imports": {
"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/"
}
},
"expectedParsedImportMap": {
"imports": {
"https://example.com:demo": "https://base.example/unparseable2",
"http://[www.example.com]/": "https://base.example/unparseable3/",
"https://example.org/": "https://base.example/invalidButParseable1/",
"https://example.com///": "https://base.example/invalidButParseable2/",
"https://example.net/": "https://base.example/prettyNormal/",
"https://example.com/": "https://base.example/percentDecoding/"
},
"scopes": {}
}
},
"Specifier keys should be sort correctly (issue #181) - Test #1": {
"importMap": {
"imports": {
"https://example.com/aaa": "https://example.com/aaa",
"https://example.com/a": "https://example.com/a"
}
},
"expectedParsedImportMap": {
"imports": {
"https://example.com/aaa": "https://example.com/aaa",
"https://example.com/a": "https://example.com/a"
},
"scopes": {}
}
},
"Specifier keys should be sort correctly (issue #181) - Test #2": {
"importMap": {
"imports": {
"https://example.com/a": "https://example.com/a",
"https://example.com/aaa": "https://example.com/aaa"
}
},
"expectedParsedImportMap": {
"imports": {
"https://example.com/aaa": "https://example.com/aaa",
"https://example.com/a": "https://example.com/a"
},
"scopes": {}
}
}
}
}

View file

@ -0,0 +1,13 @@
{
"name": "Failing addresses: mismatched trailing slashes",
"importMap": {
"imports": {
"trailer/": "/notrailer"
}
},
"importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": {
"imports": {},
"scopes": {}
}
}

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,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,175 +0,0 @@
'use strict';
const { expectSpecifierMap } = require('./helpers/parsing.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',
{
},
[
`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',
{
},
[
`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('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:http://example.com/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:http://example.com/good/'),
http: expect.toMatchURL('http://good/'),
https: expect.toMatchURL('https://good/'),
ftp: expect.toMatchURL('ftp://good/'),
import: expect.toMatchURL('import:bad'),
javascript: expect.toMatchURL('javascript:bad'),
mailto: expect.toMatchURL('mailto:bad'),
wss: expect.toMatchURL('wss://bad/')
},
[]
);
});
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',
{
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"
}`,
'https://base.example/path1/path2/path3',
{
},
[`Invalid address "https://base.example/notrailer" for package specifier key "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',
{
},
[`Invalid address "${bad}" for the specifier key "foo".`]
);
}
});
});

View file

@ -1,99 +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 = ['null', 'true', '1', '{}', '[]', '["https://example.com/"]'];
it('should ignore entries where the address is not a string', () => {
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.`]
);
}
});
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 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: {} });
});
});

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,164 +0,0 @@
'use strict';
const { expectSpecifierMap } = require('./helpers/parsing.js');
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('Accept all absolute URL specifier keys even with fetch schemes as URLs', () => {
expectSpecifierMap(
`{
"about:good": "/about",
"blob:good": "/blob",
"data:good": "/data",
"file:///good": "/file",
"filesystem:http://example.com/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:http://example.com/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 sort correctly (issue #181)', () => {
expectSpecifierMap(
`{
"https://example.com/aaa": "https://example.com/aaa",
"https://example.com/a": "https://example.com/a"
}`,
'https://base.example/',
{
'https://example.com/aaa': expect.toMatchURL('https://example.com/aaa'),
'https://example.com/a': expect.toMatchURL('https://example.com/a')
}
);
expectSpecifierMap(
`{
"https://example.com/a": "https://example.com/a",
"https://example.com/aaa": "https://example.com/aaa"
}`,
'https://base.example/',
{
'https://example.com/aaa': expect.toMatchURL('https://example.com/aaa'),
'https://example.com/a': expect.toMatchURL('https://example.com/a')
}
);
});
});

View file

@ -52,7 +52,7 @@ interface CustomEvent : Event {
readonly attribute any detail;
void initCustomEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any detail = null);
void initCustomEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any detail = null); // historical
};
dictionary CustomEventInit : EventInit {
@ -289,7 +289,7 @@ interface Document : Node {
[NewObject] Attr createAttribute(DOMString localName);
[NewObject] Attr createAttributeNS(DOMString? namespace, DOMString qualifiedName);
[NewObject] Event createEvent(DOMString interface);
[NewObject] Event createEvent(DOMString interface); // historical
[NewObject] Range createRange();

View file

@ -21,7 +21,7 @@ interface mixin AriaAttributes {
attribute FrozenArray<Element>? ariaControlsElements;
attribute DOMString? ariaCurrent;
attribute FrozenArray<Element>? ariaDescribedByElements;
attribute Element? ariaDetailsElements;
attribute Element? ariaDetailsElement;
attribute DOMString? ariaDisabled;
attribute Element? ariaErrorMessageElement;
attribute DOMString? ariaExpanded;

View file

@ -49,6 +49,10 @@ partial interface RTCPeerConnection {
readonly attribute DOMString? idpErrorInfo;
};
partial dictionary RTCConfiguration {
DOMString peerIdentity;
};
dictionary RTCIdentityProviderOptions {
DOMString protocol = "default";
DOMString usernameHint;
@ -62,6 +66,29 @@ interface RTCIdentityAssertion {
attribute DOMString name;
};
partial interface RTCError {
readonly attribute long? httpRequestStatusCode;
};
partial dictionary RTCErrorInit {
long httpRequestStatusCode;
};
// This is an extension of RTCErrorDetailType from [[WEBRTC-PC]]
// Unfortunately, WebIDL does not support partial enums (yet).
//
// partial enum RTCErrorDetailType {
enum RTCErrorDetailTypeIdp {
"idp-bad-script-failure",
"idp-execution-failure",
"idp-load-failure",
"idp-need-login",
"idp-timeout",
"idp-tls-failure",
"idp-token-expired",
"idp-token-invalid",
};
partial dictionary MediaStreamConstraints {
DOMString peerIdentity;
};

View file

@ -241,9 +241,6 @@ dictionary RTCVideoSenderStats : RTCVideoHandlerStats {
DOMString mediaSourceId;
};
dictionary RTCSenderVideoTrackAttachmentStats : RTCVideoSenderStats {
};
dictionary RTCVideoReceiverStats : RTCVideoHandlerStats {
};
@ -254,9 +251,6 @@ dictionary RTCAudioSenderStats : RTCAudioHandlerStats {
DOMString mediaSourceId;
};
dictionary RTCSenderAudioTrackAttachmentStats : RTCAudioSenderStats {
};
dictionary RTCAudioReceiverStats : RTCAudioHandlerStats {
};
@ -366,6 +360,12 @@ dictionary RTCMediaStreamStats : RTCStats {
sequence<DOMString> trackIds;
};
dictionary RTCSenderVideoTrackAttachmentStats : RTCVideoSenderStats {
};
dictionary RTCSenderAudioTrackAttachmentStats : RTCAudioSenderStats {
};
dictionary RTCReceiverVideoTrackAttachmentStats : RTCVideoReceiverStats {};
dictionary RTCReceiverAudioTrackAttachmentStats : RTCAudioReceiverStats {};

View file

@ -686,7 +686,7 @@ LAYOUTTESTS APIS: resources/chromium/nfc-mock.js
LAYOUTTESTS APIS: resources/chromium/webxr-test.js
LAYOUTTESTS APIS: web-nfc/NDEFReader-document-hidden-manual.https.html
LAYOUTTESTS APIS: web-nfc/NDEFReader_scan.https.html
LAYOUTTESTS APIS: web-nfc/NDEFWriter_push.https.html
LAYOUTTESTS APIS: web-nfc/NDEFWriter_write.https.html
# Signed Exchange files have hard-coded URLs in the certUrl field
WEB-PLATFORM.TEST:signed-exchange/resources/*.sxg

View file

@ -10,6 +10,16 @@
<script>
"use strict";
// The prefixed animation events are special; their event types are
// camel-case.
const prefixedAnimationAttributeToEventType = new Map([
["webkitanimationend", "webkitAnimationEnd"],
["webkitanimationiteration", "webkitAnimationIteration"],
["webkitanimationstart", "webkitAnimationStart"],
["webkittransitionend", "webkitTransitionEnd"],
]);
setup({ explicit_done: true });
// basic pattern lifted from /html/webappapis/scripting/events/event-handler-all-global-events.html
@ -131,7 +141,11 @@
);
let target = undefined;
element[name] = (e) => { target = e.currentTarget; }
element.dispatchEvent(new Event(withoutOn));
let eventType = withoutOn;
if (prefixedAnimationAttributeToEventType.has(eventType)) {
eventType = prefixedAnimationAttributeToEventType.get(eventType);
}
element.dispatchEvent(new Event(eventType));
assert_equals(target, element, "The event must be fired at the <math> element");
}, `${name}: dispatching an Event at a <math> element must trigger element.${name}`);
}

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Allowed content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Allowed content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Allowed content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Allowed content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Allowed content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Allowed content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Optionally-blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Allowed content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Allowed content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using common/security-features/tools/template/test.release.html.template. -->
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
<html>
<head>
<title>Mixed-Content: Blockable content</title>
@ -11,7 +11,7 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<script src="/mixed-content/generic/test-case.sub.js"></script>
<script src="../../../../generic/test-case.sub.js"></script>
</head>
<body>
<script>

Some files were not shown because too many files have changed in this diff Show more