mirror of
https://github.com/servo/servo.git
synced 2025-06-27 10:33:39 +01:00
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:
commit
a23e2dbe48
3570 changed files with 12529 additions and 11891 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,2 +0,0 @@
|
|||
[keyframes-remove-documentElement-crash.html]
|
||||
expected: TIMEOUT
|
|
@ -1,2 +1,2 @@
|
|||
[no-transition-from-ua-to-blocking-stylesheet.html]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[CaretPosition-001.html]
|
||||
[Element at (400, 100)]
|
||||
expected: FAIL
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -53,6 +53,3 @@
|
|||
[combined text/javascript ]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript x/x]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[traverse_the_history_4.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[traverse_the_history_5.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
Accept-CH: device-memory, DPR
|
||||
Accept-CH-Lifetime: 1
|
||||
Access-Control-Allow-Origin: *
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.";
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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')
|
||||
|
||||
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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}`);
|
||||
|
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
Cross-Origin-Opener-Policy: same-origin
|
|
@ -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>
|
|
@ -0,0 +1,2 @@
|
|||
Cross-Origin-Opener-Policy: same-origin
|
||||
Cross-Origin-Embedder-Policy: require-corp
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
Cross-Origin-Opener-Policy: same-origin-allow-popups
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
Cross-Origin-Opener-Policy: same-origin
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
Cross-Origin-Opener-Policy: unsafe-none
|
|
@ -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}`);
|
||||
}
|
|
@ -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>
|
|
@ -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`);
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "Invalid JSON",
|
||||
"importMapBaseURL": "https://base.example/",
|
||||
"importMap": "{imports: {}}",
|
||||
"expectedParsedImportMap": null
|
||||
}
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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/": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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/": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "Failing addresses: mismatched trailing slashes",
|
||||
"importMap": {
|
||||
"imports": {
|
||||
"trailer/": "/notrailer"
|
||||
}
|
||||
},
|
||||
"importMapBaseURL": "https://base.example/path1/path2/path3",
|
||||
"expectedParsedImportMap": {
|
||||
"imports": {},
|
||||
"scopes": {}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-addresses.js
|
||||
-->
|
||||
<script type="module" src="resources/parsing-addresses.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-schema.js
|
||||
-->
|
||||
<script type="module" src="resources/parsing-schema.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-scope-keys.js
|
||||
-->
|
||||
<script type="module" src="resources/parsing-scope-keys.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-specifier-keys.js
|
||||
-->
|
||||
<script type="module" src="resources/parsing-specifier-keys.js"></script>
|
|
@ -1,44 +0,0 @@
|
|||
'use strict';
|
||||
const { parseFromString } = require('../../lib/parser.js');
|
||||
|
||||
// Local modifications from upstream:
|
||||
// Currently warnings and scopes are not checked in expectSpecifierMap().
|
||||
exports.expectSpecifierMap = (input, baseURL, output, warnings = []) => {
|
||||
expect(parseFromString(`{ "imports": ${input} }`, baseURL))
|
||||
.toEqual({ imports: output, scopes: {} });
|
||||
};
|
||||
|
||||
exports.expectScopes = (inputArray, baseURL, outputArray, warnings = []) => {
|
||||
const checkWarnings = testWarningHandler(warnings);
|
||||
|
||||
const inputScopesAsStrings = inputArray.map(scopePrefix => `${JSON.stringify(scopePrefix)}: {}`);
|
||||
const inputString = `{ "scopes": { ${inputScopesAsStrings.join(', ')} } }`;
|
||||
|
||||
const outputScopesObject = {};
|
||||
for (const outputScopePrefix of outputArray) {
|
||||
outputScopesObject[outputScopePrefix] = {};
|
||||
}
|
||||
|
||||
expect(parseFromString(inputString, baseURL)).toEqual({ imports: {}, scopes: outputScopesObject });
|
||||
|
||||
checkWarnings();
|
||||
};
|
||||
|
||||
exports.expectBad = (input, baseURL, warnings = []) => {
|
||||
const checkWarnings = testWarningHandler(warnings);
|
||||
expect(() => parseFromString(input, baseURL)).toThrow(TypeError);
|
||||
checkWarnings();
|
||||
};
|
||||
|
||||
exports.expectWarnings = (input, baseURL, output, warnings = []) => {
|
||||
const checkWarnings = testWarningHandler(warnings);
|
||||
expect(parseFromString(input, baseURL)).toEqual(output);
|
||||
|
||||
checkWarnings();
|
||||
};
|
||||
|
||||
function testWarningHandler(expectedWarnings) {
|
||||
// We don't check warnings on WPT tests, because there are no
|
||||
// ways to catch console warnings from JavaScript.
|
||||
return () => {};
|
||||
}
|
|
@ -1,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".`]
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -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: {} });
|
||||
});
|
||||
});
|
|
@ -1,144 +0,0 @@
|
|||
'use strict';
|
||||
const { expectScopes } = require('./helpers/parsing.js');
|
||||
|
||||
describe('Relative URL scope keys', () => {
|
||||
it('should work with no prefix', () => {
|
||||
expectScopes(
|
||||
['foo'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
['https://base.example/path1/path2/foo']
|
||||
);
|
||||
});
|
||||
|
||||
it('should work with ./, ../, and / prefixes', () => {
|
||||
expectScopes(
|
||||
['./foo', '../foo', '/foo'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
[
|
||||
'https://base.example/path1/path2/foo',
|
||||
'https://base.example/path1/foo',
|
||||
'https://base.example/foo'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should work with /s, ?s, and #s', () => {
|
||||
expectScopes(
|
||||
['foo/bar?baz#qux'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
['https://base.example/path1/path2/foo/bar?baz#qux']
|
||||
);
|
||||
});
|
||||
|
||||
it('should work with an empty string scope key', () => {
|
||||
expectScopes(
|
||||
[''],
|
||||
'https://base.example/path1/path2/path3',
|
||||
['https://base.example/path1/path2/path3']
|
||||
);
|
||||
});
|
||||
|
||||
it('should work with / suffixes', () => {
|
||||
expectScopes(
|
||||
['foo/', './foo/', '../foo/', '/foo/', '/foo//'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
[
|
||||
'https://base.example/path1/path2/foo/',
|
||||
'https://base.example/path1/path2/foo/',
|
||||
'https://base.example/path1/foo/',
|
||||
'https://base.example/foo/',
|
||||
'https://base.example/foo//'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should deduplicate based on URL parsing rules', () => {
|
||||
expectScopes(
|
||||
['foo/\\', 'foo//', 'foo\\\\'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
['https://base.example/path1/path2/foo//']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Absolute URL scope keys', () => {
|
||||
it('should accept all absolute URL scope keys, with or without fetch schemes', () => {
|
||||
expectScopes(
|
||||
[
|
||||
'about:good',
|
||||
'blob:good',
|
||||
'data:good',
|
||||
'file:///good',
|
||||
'filesystem:http://example.com/good/',
|
||||
'http://good/',
|
||||
'https://good/',
|
||||
'ftp://good/',
|
||||
'import:bad',
|
||||
'mailto:bad',
|
||||
'javascript:bad',
|
||||
'wss:ba'
|
||||
],
|
||||
'https://base.example/path1/path2/path3',
|
||||
[
|
||||
'about:good',
|
||||
'blob:good',
|
||||
'data:good',
|
||||
'file:///good',
|
||||
'filesystem:http://example.com/good/',
|
||||
'http://good/',
|
||||
'https://good/',
|
||||
'ftp://good/',
|
||||
'import:bad',
|
||||
'mailto:bad',
|
||||
'javascript:bad',
|
||||
'wss://ba/'
|
||||
],
|
||||
[]
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse absolute URL scope keys, ignoring unparseable ones', () => {
|
||||
expectScopes(
|
||||
[
|
||||
'https://ex ample.org/',
|
||||
'https://example.com:demo',
|
||||
'http://[www.example.com]/',
|
||||
'https:example.org',
|
||||
'https://///example.com///',
|
||||
'https://example.net',
|
||||
'https://ex%41mple.com/foo/',
|
||||
'https://example.com/%41'
|
||||
],
|
||||
'https://base.example/path1/path2/path3',
|
||||
[
|
||||
'https://base.example/path1/path2/example.org', // tricky case! remember we have a base URL
|
||||
'https://example.com///',
|
||||
'https://example.net/',
|
||||
'https://example.com/foo/',
|
||||
'https://example.com/%41'
|
||||
],
|
||||
[
|
||||
'Invalid scope "https://ex ample.org/" (parsed against base URL "https://base.example/path1/path2/path3").',
|
||||
'Invalid scope "https://example.com:demo" (parsed against base URL "https://base.example/path1/path2/path3").',
|
||||
'Invalid scope "http://[www.example.com]/" (parsed against base URL "https://base.example/path1/path2/path3").'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should ignore relative URL scope keys when the base URL is a data: URL', () => {
|
||||
expectScopes(
|
||||
[
|
||||
'./foo',
|
||||
'../foo',
|
||||
'/foo'
|
||||
],
|
||||
'data:text/html,test',
|
||||
[],
|
||||
[
|
||||
'Invalid scope "./foo" (parsed against base URL "data:text/html,test").',
|
||||
'Invalid scope "../foo" (parsed against base URL "data:text/html,test").',
|
||||
'Invalid scope "/foo" (parsed against base URL "data:text/html,test").'
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,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')
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}`);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue