mirror of
https://github.com/servo/servo.git
synced 2025-08-21 13:25:34 +01:00
Update web-platform-tests to revision ad219567030d1f99f7310f52a17546b57b70d29e
This commit is contained in:
parent
2c63d1296b
commit
a7e62acbe8
129 changed files with 4156 additions and 590 deletions
|
@ -0,0 +1 @@
|
|||
Content-Type: text/javascript
|
1
tests/wpt/web-platform-tests/import-maps/@std/blank
Normal file
1
tests/wpt/web-platform-tests/import-maps/@std/blank
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:@std/blank");
|
1
tests/wpt/web-platform-tests/import-maps/@std/none
Normal file
1
tests/wpt/web-platform-tests/import-maps/@std/none
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:@std/none");
|
9
tests/wpt/web-platform-tests/import-maps/README.md
Normal file
9
tests/wpt/web-platform-tests/import-maps/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
Tests for [Import Maps](https://github.com/WICG/import-maps).
|
||||
|
||||
Because the spec itself is still under development and there are ongoing spec
|
||||
discussions, the tests are all tentative.
|
||||
|
||||
Also, some tests are based on Chromium's behavior which reflects an older
|
||||
version of import maps spec ("package name maps" around May 2018), and have
|
||||
dependency to Chromium's implementation (internals.resolveModuleSpecifier).
|
||||
These dependencies should be removed, once the spec matures.
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
// https://github.com/WICG/import-maps/blob/master/spec.md#when-import-maps-can-be-encountered
|
||||
const t = async_test(
|
||||
'After dynamic imports, import maps should fire error events');
|
||||
const log = [];
|
||||
// To ensure we are testing that the flag is cleared at the beginning of module
|
||||
// script loading unconditionally, not at the end of loading or not at the
|
||||
// first attempt to resolve a module specifier, trickle(d1) is used to ensure
|
||||
// the following import map is added after module loading is triggered but
|
||||
// before the first module script is parsed.
|
||||
promise_test(() => import('../../resources/empty.js?pipe=trickle(d1)'),
|
||||
"A dynamic import succeeds");
|
||||
</script>
|
||||
<script type="importmap" onload="t.assert_unreached('onload')" onerror="t.done()">
|
||||
{
|
||||
"imports": {
|
||||
"../../resources/log.js?pipe=sub&name=A": "../../resources/log.js?pipe=sub&name=B"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
promise_test(() => {
|
||||
return import("../../resources/log.js?pipe=sub&name=A")
|
||||
.then(() => assert_array_equals(log, ["log:A"]))
|
||||
},
|
||||
'After a dynamic import(), import maps are not effective');
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
// https://github.com/WICG/import-maps/blob/master/spec.md#when-import-maps-can-be-encountered
|
||||
const t = async_test(
|
||||
'After <script type="module"> import maps should fire error events');
|
||||
const log = [];
|
||||
</script>
|
||||
<script type="module" src="../../resources/empty.js?pipe=trickle(d1)"></script>
|
||||
<script type="importmap" onerror="t.done()">
|
||||
{
|
||||
"imports": {
|
||||
"../../resources/log.js?pipe=sub&name=A": "../../resources/log.js?pipe=sub&name=B"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
promise_test(() => {
|
||||
return import("../../resources/log.js?pipe=sub&name=A")
|
||||
.then(() => assert_array_equals(log, ["log:A"]))
|
||||
},
|
||||
'After <script type="module"> import maps are not effective');
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
// https://github.com/WICG/import-maps/blob/master/spec.md#when-import-maps-can-be-encountered
|
||||
const t = async_test(
|
||||
'After module worker creation, import maps should fire error events');
|
||||
const log = [];
|
||||
new Worker('../../resources/empty.js?pipe=trickle(d1)', {type: "module"});
|
||||
</script>
|
||||
<script type="importmap" onerror="t.done()">
|
||||
{
|
||||
"imports": {
|
||||
"../../resources/log.js?pipe=sub&name=A": "../../resources/log.js?pipe=sub&name=B"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
promise_test(() => {
|
||||
return import("../../resources/log.js?pipe=sub&name=A")
|
||||
.then(() => assert_array_equals(log, ["A"]))
|
||||
},
|
||||
'After module worker creation import maps are not effective');
|
||||
</script>
|
|
@ -0,0 +1,70 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// "bare/..." (i.e. without leading "./") are bare specifiers
|
||||
// (not relative paths).
|
||||
//
|
||||
// Discussions about notations for builtin modules are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update the tests.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"bare/bare": "./resources/log.js?pipe=sub&name=bare",
|
||||
"bare/cross-origin-bare": "https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-bare",
|
||||
"bare/to-data": "data:text/javascript,log.push('dataURL')",
|
||||
|
||||
"bare/std-blank": "std:blank",
|
||||
"bare/blank": "@std/blank",
|
||||
"bare/std-none": "std:none",
|
||||
"bare/none": "@std/none",
|
||||
|
||||
"bare/to-bare": "bare/bare"
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Currently, Chromium's implementation resolves import maps as a part of
|
||||
// specifier resolution, and thus failure in import map resolution causes
|
||||
// a parse error, not fetch error. Therefore, we use Result.PARSE_ERROR
|
||||
// below. https://crbug.com/928435
|
||||
|
||||
// Bare to HTTP(S).
|
||||
"bare/bare":
|
||||
[Result.URL, Result.URL, "log:bare", "log:bare"],
|
||||
"bare/cross-origin-bare":
|
||||
[Result.URL, Result.URL, "log:cross-origin-bare", "log:cross-origin-bare"],
|
||||
|
||||
// Bare to data:
|
||||
"bare/to-data":
|
||||
[Result.URL, Result.URL, "dataURL", "dataURL"],
|
||||
|
||||
// Bare to built-in.
|
||||
"bare/std-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"bare/blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"bare/std-none":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
"bare/none":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
|
||||
// Bare to bare mapping is disabled.
|
||||
"bare/to-bare":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -0,0 +1 @@
|
|||
Content-Type: text/javascript
|
1
tests/wpt/web-platform-tests/import-maps/bare/bare
Normal file
1
tests/wpt/web-platform-tests/import-maps/bare/bare
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:bare/bare");
|
1
tests/wpt/web-platform-tests/import-maps/bare/blank
Normal file
1
tests/wpt/web-platform-tests/import-maps/bare/blank
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:bare/blank");
|
|
@ -0,0 +1 @@
|
|||
log.push("relative:bare/cross-origin-bare");
|
1
tests/wpt/web-platform-tests/import-maps/bare/none
Normal file
1
tests/wpt/web-platform-tests/import-maps/bare/none
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:bare/none");
|
1
tests/wpt/web-platform-tests/import-maps/bare/std-blank
Normal file
1
tests/wpt/web-platform-tests/import-maps/bare/std-blank
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:bare/std-blank");
|
1
tests/wpt/web-platform-tests/import-maps/bare/std-none
Normal file
1
tests/wpt/web-platform-tests/import-maps/bare/std-none
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:bare/std-none");
|
1
tests/wpt/web-platform-tests/import-maps/bare/to-bare
Normal file
1
tests/wpt/web-platform-tests/import-maps/bare/to-bare
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:bare/to-bare");
|
1
tests/wpt/web-platform-tests/import-maps/bare/to-data
Normal file
1
tests/wpt/web-platform-tests/import-maps/bare/to-data
Normal file
|
@ -0,0 +1 @@
|
|||
log.push("relative:bare/to-data");
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"./resources/log.js?pipe=sub&name=empty": [ "@std/" ],
|
||||
"./resources/log.js?pipe=sub&name=empty-fallback": [
|
||||
"@std/",
|
||||
"./resources/log.js?pipe=sub&name=empty-fallback"
|
||||
]
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Discussions about notations are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update this and related tests.
|
||||
"std:":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"@std/":
|
||||
[Result.FETCH_ERROR, Result.PARSE_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
|
||||
"./resources/log.js?pipe=sub&name=empty":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
"./resources/log.js?pipe=sub&name=empty-fallback":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Currently direct use of import: URLs are disabled.
|
||||
"import:std:blank":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"import:@std/blank":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"import:std:none":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"import:@std/none":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
};
|
||||
|
||||
doTests(null, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Discussions about notations are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update this and related tests.
|
||||
"std:blank":
|
||||
[Result.BUILTIN, Result.FETCH_ERROR, Result.BUILTIN, Result.BUILTIN],
|
||||
"@std/blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"std:none":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"@std/none":
|
||||
[Result.URL, Result.URL, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
};
|
||||
|
||||
doTests(null, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -0,0 +1,72 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// "bare/..." (i.e. without leading "./") are bare specifiers
|
||||
// (not relative paths).
|
||||
//
|
||||
// Discussions about notations for builtin modules are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update the tests.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"bare": "./resources/log.js?pipe=sub&name=bare",
|
||||
|
||||
"data:text/javascript,log.push('data:foo')": "./resources/log.js?pipe=sub&name=foo",
|
||||
"data:text/javascript,log.push('data:cross-origin-foo')": "https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-foo",
|
||||
"data:text/javascript,log.push('data:to-data')": "data:text/javascript,log.push('dataURL')",
|
||||
|
||||
"data:text/javascript,log.push('data:std-blank')": "std:blank",
|
||||
"data:text/javascript,log.push('data:blank')": "@std/blank",
|
||||
"data:text/javascript,log.push('data:std-none')": "std:none",
|
||||
"data:text/javascript,log.push('data:none')": "@std/none",
|
||||
|
||||
"data:text/javascript,log.push('data:to-bare')": "bare"
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Currently, Chromium's implementation resolves import maps as a part of
|
||||
// specifier resolution, and thus failure in import map resolution causes
|
||||
// a parse error, not fetch error. Therefore, we use Result.PARSE_ERROR
|
||||
// below. https://crbug.com/928435
|
||||
|
||||
// data: to HTTP(S).
|
||||
"data:text/javascript,log.push('data:foo')":
|
||||
[Result.URL, Result.URL, "log:foo", "log:foo"],
|
||||
"data:text/javascript,log.push('data:cross-origin-foo')":
|
||||
[Result.URL, Result.URL, "log:cross-origin-foo", "log:cross-origin-foo"],
|
||||
|
||||
// data: to data:
|
||||
"data:text/javascript,log.push('data:to-data')":
|
||||
[Result.URL, Result.URL, "dataURL", "dataURL"],
|
||||
|
||||
// data: to built-in.
|
||||
"data:text/javascript,log.push('data:std-blank')":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"data:text/javascript,log.push('data:blank')":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"data:text/javascript,log.push('data:std-none')":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
"data:text/javascript,log.push('data:none')":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
|
||||
// data: to bare mapping is disabled.
|
||||
"data:text/javascript,log.push('data:to-bare')":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// Fallbacks from external URLs (such as HTTPS URLs) are
|
||||
// blocked by ongoing spec discussions, for example
|
||||
// https://github.com/WICG/import-maps/issues/76.
|
||||
// https://crbug.com/928435
|
||||
//
|
||||
// This test, as well as Chromium's implementation, rejects broader range of
|
||||
// fallbacks (not only those from HTTPS), to avoid potential spec and
|
||||
// interoperability issues.
|
||||
// The only allowed fallback pattern is fallbacks from bare specifiers with
|
||||
// two elements, which are listed in fallback.sub.tentative.html.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"bare": "./resources/log.js?pipe=sub&name=bare",
|
||||
|
||||
"./resources/log.js?pipe=sub&name=http-to-builtin": [
|
||||
"./resources/log.js?pipe=sub&name=http-to-builtin",
|
||||
"@std/blank"
|
||||
],
|
||||
|
||||
"./resources/log.js?pipe=sub&name=fallback-to-different-url-1": [
|
||||
"@std/blank",
|
||||
"./resources/log.js?pipe=sub&name=something-different"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=fallback-to-different-url-2": [
|
||||
"@std/none",
|
||||
"./resources/log.js?pipe=sub&name=something-different2"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=fallback-to-different-origin-1": [
|
||||
"@std/blank",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=fallback-to-different-origin-1"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=fallback-to-different-origin-2": [
|
||||
"@std/none",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=fallback-to-different-origin-2"
|
||||
],
|
||||
|
||||
"./resources/log.js?pipe=sub&name=more-than-two-values-1": [
|
||||
"@std/none",
|
||||
"@std/blank",
|
||||
"./resources/log.js?pipe=sub&name=more-than-two-values-1"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=more-than-two-values-2": [
|
||||
"@std/none",
|
||||
"./resources/log.js?pipe=sub&name=more-than-two-values-2",
|
||||
"@std/blank"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=fallback-from-http": [
|
||||
"./resources/log.js?pipe=sub&name=non-built-in",
|
||||
"./resources/log.js?pipe=sub&name=fallback-from-http"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=fallback-from-data-1": [
|
||||
"data:text/plain,",
|
||||
"./resources/log.js?pipe=sub&name=fallback-from-http"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=fallback-from-data-2": [
|
||||
"data:text/javascript,log.push('dataURL')",
|
||||
"./resources/log.js?pipe=sub&name=fallback-from-http"
|
||||
]
|
||||
}
|
||||
}
|
||||
`;
|
||||
const tests = {};
|
||||
for (const key in JSON.parse(importMap).imports) {
|
||||
if (key === "bare") {
|
||||
continue;
|
||||
}
|
||||
tests[key] =
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR];
|
||||
}
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// This tests is for fallbacks with the pattern of
|
||||
// `"https://some.external/url": ["@std/x", "https://some.external/url"]`
|
||||
// which maps "https://some.external/url" to "@std/x" if "@std/x" is
|
||||
// implemented, or leaves it unmodified otherwise.
|
||||
//
|
||||
// This is the primary use case where fallback should work.
|
||||
// Some other patterns of fallbacks are intentionally blocked due to ongoing
|
||||
// spec issues. See fallback-disallowed.sub.tentative.html.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"./resources/log.js?pipe=sub&name=blank": [
|
||||
"@std/blank",
|
||||
"./resources/log.js?pipe=sub&name=blank"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=none": [
|
||||
"@std/none",
|
||||
"./resources/log.js?pipe=sub&name=none"
|
||||
],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-blank": [
|
||||
"@std/blank",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-blank"
|
||||
],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-none": [
|
||||
"@std/none",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-none"
|
||||
],
|
||||
|
||||
"./resources/log.js?pipe=sub&name=std-blank": [
|
||||
"std:blank",
|
||||
"./resources/log.js?pipe=sub&name=std-blank"
|
||||
],
|
||||
"./resources/log.js?pipe=sub&name=std-none": [
|
||||
"std:none",
|
||||
"./resources/log.js?pipe=sub&name=std-none"
|
||||
],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-blank": [
|
||||
"std:blank",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-blank"
|
||||
],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-none": [
|
||||
"std:none",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-none"
|
||||
]
|
||||
|
||||
}
|
||||
}
|
||||
`;
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
// Result.URL indicates that the specifier was not re-mapped by import maps,
|
||||
// i.e. either considered as a relative path, or fallback occured.
|
||||
"./resources/log.js?pipe=sub&name=blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"./resources/log.js?pipe=sub&name=none":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-none":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
|
||||
"./resources/log.js?pipe=sub&name=std-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"./resources/log.js?pipe=sub&name=std-none":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-none":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -0,0 +1,72 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// "bare/..." (i.e. without leading "./") are bare specifiers
|
||||
// (not relative paths).
|
||||
//
|
||||
// Discussions about notations for builtin modules are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update the tests.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"bare": "./resources/log.js?pipe=sub&name=bare",
|
||||
|
||||
"./resources/log.js?pipe=sub&name=foo": "./resources/log.js?pipe=sub&name=bar",
|
||||
"./resources/log.js?pipe=sub&name=cross-origin-foo": "https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-bar",
|
||||
"./resources/log.js?pipe=sub&name=to-data": "data:text/javascript,log.push('dataURL')",
|
||||
|
||||
"./resources/log.js?pipe=sub&name=std-blank": "std:blank",
|
||||
"./resources/log.js?pipe=sub&name=blank": "@std/blank",
|
||||
"./resources/log.js?pipe=sub&name=std-none": "std:none",
|
||||
"./resources/log.js?pipe=sub&name=none": "@std/none",
|
||||
|
||||
"./resources/log.js?pipe=sub&name=to-bare": "bare"
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Currently, Chromium's implementation resolves import maps as a part of
|
||||
// specifier resolution, and thus failure in import map resolution causes
|
||||
// a parse error, not fetch error. Therefore, we use Result.PARSE_ERROR
|
||||
// below. https://crbug.com/928435
|
||||
|
||||
// HTTP(S) to HTTP(S).
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=foo":
|
||||
[Result.URL, Result.URL, "log:bar", "log:bar"],
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-foo":
|
||||
[Result.URL, Result.URL, "log:cross-origin-bar", "log:cross-origin-bar"],
|
||||
|
||||
// HTTP(S) to data:
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=to-data":
|
||||
[Result.URL, Result.URL, "dataURL", "dataURL"],
|
||||
|
||||
// HTTP(S) to built-in.
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=std-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=std-none":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=none":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
|
||||
// HTTP(S) to bare mapping is disabled.
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=to-bare":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"./resources/log.js?pipe=sub&name=A": "./resources/log.js?pipe=sub&name=B"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
const log = [];
|
||||
|
||||
// This test reflects the Chromium's current implementation.
|
||||
// If the import map resolution is moved into the fetch spec, the module map's
|
||||
// key will become the URL/specifier BEFORE import map resolution.
|
||||
// https://crbug.com/928435
|
||||
promise_test(() => {
|
||||
return import("./resources/log.js?pipe=sub&name=A")
|
||||
.then(() => import("./resources/log.js?pipe=sub&name=B"))
|
||||
.then(() => assert_array_equals(log, ["log:B"]))
|
||||
},
|
||||
"Module map's key is the URL after import map resolution");
|
||||
</script>
|
|
@ -0,0 +1,81 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception : true});
|
||||
|
||||
// Hacky glue code to run Jest-based tests as WPT tests.
|
||||
// Only supports resolving.js.
|
||||
function require(name) {
|
||||
return {
|
||||
'URL': URL,
|
||||
'parseFromString': parseFromString,
|
||||
'resolve': resolve
|
||||
};
|
||||
}
|
||||
|
||||
function expect(v) {
|
||||
return {
|
||||
toMatchURL: expected => assert_equals(v, expected),
|
||||
toThrow: expected => assert_throws(expected(), v)
|
||||
};
|
||||
}
|
||||
|
||||
let current_message = '';
|
||||
function describe(message, f) {
|
||||
const old = current_message;
|
||||
if (current_message !== '') {
|
||||
current_message += ' / ';
|
||||
}
|
||||
current_message += message;
|
||||
f();
|
||||
current_message = old;
|
||||
}
|
||||
function it(message, f) {
|
||||
const old = current_message;
|
||||
if (current_message !== '') {
|
||||
current_message += ' / ';
|
||||
}
|
||||
current_message += message;
|
||||
test(t => t.step_func(f)(), current_message);
|
||||
current_message = old;
|
||||
}
|
||||
|
||||
// Creates a new Document (via <iframe>) and add an inline import map.
|
||||
// Currently document.write() is used to make everything synchronous, which
|
||||
// is just needed for running the existing Jest-based tests easily.
|
||||
function parseFromString(mapString, mapBaseURL) {
|
||||
const iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
iframe.contentDocument.write(`
|
||||
<base href="${mapBaseURL}">
|
||||
<script>
|
||||
let isError = false;
|
||||
function onError() {
|
||||
isError = true;
|
||||
}
|
||||
</sc` + `ript>
|
||||
<script type="importmap" onerror="onError()">
|
||||
${mapString}
|
||||
</sc` + `ript>
|
||||
`);
|
||||
iframe.contentDocument.close();
|
||||
return iframe;
|
||||
}
|
||||
|
||||
// URL resolution is tested using Chromium's `internals`.
|
||||
// TODO(hiroshige): Remove the Chromium-specific dependency.
|
||||
function resolve(specifier, map, baseURL) {
|
||||
return internals.resolveModuleSpecifier(specifier,
|
||||
baseURL,
|
||||
map.contentDocument);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!--
|
||||
resolving.js is
|
||||
https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving.js
|
||||
-->
|
||||
<script type="module" src="resources/resolving.js"></script>
|
|
@ -0,0 +1 @@
|
|||
log.push("log:{{GET[name]}}");
|
|
@ -0,0 +1 @@
|
|||
Access-Control-Allow-Origin: *
|
206
tests/wpt/web-platform-tests/import-maps/resources/resolving.js
Normal file
206
tests/wpt/web-platform-tests/import-maps/resources/resolving.js
Normal file
|
@ -0,0 +1,206 @@
|
|||
'use strict';
|
||||
const { URL } = require('url');
|
||||
const { parseFromString } = require('../lib/parser.js');
|
||||
const { resolve } = require('../lib/resolver.js');
|
||||
|
||||
const mapBaseURL = new URL('https://example.com/app/index.html');
|
||||
const scriptURL = new URL('https://example.com/js/app.mjs');
|
||||
|
||||
function makeResolveUnderTest(mapString) {
|
||||
const map = parseFromString(mapString, mapBaseURL);
|
||||
return specifier => resolve(specifier, map, scriptURL);
|
||||
}
|
||||
|
||||
describe('Unmapped', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{}`);
|
||||
|
||||
it('should resolve ./ specifiers as URLs', () => {
|
||||
expect(resolveUnderTest('./foo')).toMatchURL('https://example.com/js/foo');
|
||||
expect(resolveUnderTest('./foo/bar')).toMatchURL('https://example.com/js/foo/bar');
|
||||
expect(resolveUnderTest('./foo/../bar')).toMatchURL('https://example.com/js/bar');
|
||||
expect(resolveUnderTest('./foo/../../bar')).toMatchURL('https://example.com/bar');
|
||||
});
|
||||
|
||||
it('should resolve ../ specifiers as URLs', () => {
|
||||
expect(resolveUnderTest('../foo')).toMatchURL('https://example.com/foo');
|
||||
expect(resolveUnderTest('../foo/bar')).toMatchURL('https://example.com/foo/bar');
|
||||
expect(resolveUnderTest('../../../foo/bar')).toMatchURL('https://example.com/foo/bar');
|
||||
});
|
||||
|
||||
it('should resolve / specifiers as URLs', () => {
|
||||
expect(resolveUnderTest('/foo')).toMatchURL('https://example.com/foo');
|
||||
expect(resolveUnderTest('/foo/bar')).toMatchURL('https://example.com/foo/bar');
|
||||
expect(resolveUnderTest('/../../foo/bar')).toMatchURL('https://example.com/foo/bar');
|
||||
expect(resolveUnderTest('/../foo/../bar')).toMatchURL('https://example.com/bar');
|
||||
});
|
||||
|
||||
it('should parse absolute fetch-scheme URLs', () => {
|
||||
expect(resolveUnderTest('about:good')).toMatchURL('about:good');
|
||||
expect(resolveUnderTest('https://example.net')).toMatchURL('https://example.net/');
|
||||
expect(resolveUnderTest('https://ex%41mple.com/')).toMatchURL('https://example.com/');
|
||||
expect(resolveUnderTest('https:example.org')).toMatchURL('https://example.org/');
|
||||
expect(resolveUnderTest('https://///example.com///')).toMatchURL('https://example.com///');
|
||||
});
|
||||
|
||||
it('should fail for absolute non-fetch-scheme URLs', () => {
|
||||
expect(() => resolveUnderTest('mailto:bad')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('import:bad')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('javascript:bad')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('wss:bad')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it('should fail for strings not parseable as absolute URLs and not starting with ./ ../ or /', () => {
|
||||
expect(() => resolveUnderTest('foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('\\foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest(':foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('@foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('%2E/foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('%2E%2E/foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('.%2Ffoo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('https://ex ample.org/')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('https://example.com:demo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('http://[www.example.com]/')).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Mapped using the "imports" key only (no scopes)', () => {
|
||||
it('should fail when the mapping is to an empty array', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"moment": null,
|
||||
"lodash": []
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(() => resolveUnderTest('moment')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('lodash')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
describe('Package-like scenarios', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"moment": "/node_modules/moment/src/moment.js",
|
||||
"moment/": "/node_modules/moment/src/",
|
||||
"lodash-dot": "./node_modules/lodash-es/lodash.js",
|
||||
"lodash-dot/": "./node_modules/lodash-es/",
|
||||
"lodash-dotdot": "../node_modules/lodash-es/lodash.js",
|
||||
"lodash-dotdot/": "../node_modules/lodash-es/"
|
||||
}
|
||||
}`);
|
||||
|
||||
it('should work for package main modules', () => {
|
||||
expect(resolveUnderTest('moment')).toMatchURL('https://example.com/node_modules/moment/src/moment.js');
|
||||
expect(resolveUnderTest('lodash-dot')).toMatchURL('https://example.com/app/node_modules/lodash-es/lodash.js');
|
||||
expect(resolveUnderTest('lodash-dotdot')).toMatchURL('https://example.com/node_modules/lodash-es/lodash.js');
|
||||
});
|
||||
|
||||
it('should work for package submodules', () => {
|
||||
expect(resolveUnderTest('moment/foo')).toMatchURL('https://example.com/node_modules/moment/src/foo');
|
||||
expect(resolveUnderTest('lodash-dot/foo')).toMatchURL('https://example.com/app/node_modules/lodash-es/foo');
|
||||
expect(resolveUnderTest('lodash-dotdot/foo')).toMatchURL('https://example.com/node_modules/lodash-es/foo');
|
||||
});
|
||||
|
||||
it('should work for package names that end in a slash by just passing through', () => {
|
||||
// TODO: is this the right behavior, or should we throw?
|
||||
expect(resolveUnderTest('moment/')).toMatchURL('https://example.com/node_modules/moment/src/');
|
||||
});
|
||||
|
||||
it('should still fail for package modules that are not declared', () => {
|
||||
expect(() => resolveUnderTest('underscore/')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('underscore/foo')).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tricky specifiers', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"package/withslash": "/node_modules/package-with-slash/index.mjs",
|
||||
"not-a-package": "/lib/not-a-package.mjs",
|
||||
".": "/lib/dot.mjs",
|
||||
"..": "/lib/dotdot.mjs",
|
||||
"..\\\\": "/lib/dotdotbackslash.mjs",
|
||||
"%2E": "/lib/percent2e.mjs",
|
||||
"%2F": "/lib/percent2f.mjs"
|
||||
}
|
||||
}`);
|
||||
|
||||
it('should work for explicitly-mapped specifiers that happen to have a slash', () => {
|
||||
expect(resolveUnderTest('package/withslash')).toMatchURL('https://example.com/node_modules/package-with-slash/index.mjs');
|
||||
});
|
||||
|
||||
it('should work when the specifier has punctuation', () => {
|
||||
expect(resolveUnderTest('.')).toMatchURL('https://example.com/lib/dot.mjs');
|
||||
expect(resolveUnderTest('..')).toMatchURL('https://example.com/lib/dotdot.mjs');
|
||||
expect(resolveUnderTest('..\\')).toMatchURL('https://example.com/lib/dotdotbackslash.mjs');
|
||||
expect(resolveUnderTest('%2E')).toMatchURL('https://example.com/lib/percent2e.mjs');
|
||||
expect(resolveUnderTest('%2F')).toMatchURL('https://example.com/lib/percent2f.mjs');
|
||||
});
|
||||
|
||||
it('should fail for attempting to get a submodule of something not declared with a trailing slash', () => {
|
||||
expect(() => resolveUnderTest('not-a-package/foo')).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('URL-like specifiers', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"/node_modules/als-polyfill/index.mjs": "@std/kv-storage",
|
||||
|
||||
"/lib/foo.mjs": "./more/bar.mjs",
|
||||
"./dotrelative/foo.mjs": "/lib/dot.mjs",
|
||||
"../dotdotrelative/foo.mjs": "/lib/dotdot.mjs",
|
||||
|
||||
"/lib/no.mjs": null,
|
||||
"./dotrelative/no.mjs": [],
|
||||
|
||||
"/": "/lib/slash-only.mjs",
|
||||
"./": "/lib/dotslash-only.mjs",
|
||||
|
||||
"/test": "/lib/test1.mjs",
|
||||
"../test": "/lib/test2.mjs"
|
||||
}
|
||||
}`);
|
||||
|
||||
it('should remap to built-in modules', () => {
|
||||
expect(resolveUnderTest('/node_modules/als-polyfill/index.mjs')).toMatchURL('import:@std/kv-storage');
|
||||
expect(resolveUnderTest('https://example.com/node_modules/als-polyfill/index.mjs')).toMatchURL('import:@std/kv-storage');
|
||||
expect(resolveUnderTest('https://///example.com/node_modules/als-polyfill/index.mjs')).toMatchURL('import:@std/kv-storage');
|
||||
});
|
||||
|
||||
it('should remap to other URLs', () => {
|
||||
expect(resolveUnderTest('https://example.com/lib/foo.mjs')).toMatchURL('https://example.com/app/more/bar.mjs');
|
||||
expect(resolveUnderTest('https://///example.com/lib/foo.mjs')).toMatchURL('https://example.com/app/more/bar.mjs');
|
||||
expect(resolveUnderTest('/lib/foo.mjs')).toMatchURL('https://example.com/app/more/bar.mjs');
|
||||
|
||||
expect(resolveUnderTest('https://example.com/app/dotrelative/foo.mjs')).toMatchURL('https://example.com/lib/dot.mjs');
|
||||
expect(resolveUnderTest('../app/dotrelative/foo.mjs')).toMatchURL('https://example.com/lib/dot.mjs');
|
||||
|
||||
expect(resolveUnderTest('https://example.com/dotdotrelative/foo.mjs')).toMatchURL('https://example.com/lib/dotdot.mjs');
|
||||
expect(resolveUnderTest('../dotdotrelative/foo.mjs')).toMatchURL('https://example.com/lib/dotdot.mjs');
|
||||
});
|
||||
|
||||
it('should fail for URLs that remap to empty arrays', () => {
|
||||
expect(() => resolveUnderTest('https://example.com/lib/no.mjs')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('/lib/no.mjs')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('../lib/no.mjs')).toThrow(TypeError);
|
||||
|
||||
expect(() => resolveUnderTest('https://example.com/app/dotrelative/no.mjs')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('/app/dotrelative/no.mjs')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('../app/dotrelative/no.mjs')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it('should remap URLs that are just composed from / and .', () => {
|
||||
expect(resolveUnderTest('https://example.com/')).toMatchURL('https://example.com/lib/slash-only.mjs');
|
||||
expect(resolveUnderTest('/')).toMatchURL('https://example.com/lib/slash-only.mjs');
|
||||
expect(resolveUnderTest('../')).toMatchURL('https://example.com/lib/slash-only.mjs');
|
||||
|
||||
expect(resolveUnderTest('https://example.com/app/')).toMatchURL('https://example.com/lib/dotslash-only.mjs');
|
||||
expect(resolveUnderTest('/app/')).toMatchURL('https://example.com/lib/dotslash-only.mjs');
|
||||
expect(resolveUnderTest('../app/')).toMatchURL('https://example.com/lib/dotslash-only.mjs');
|
||||
});
|
||||
|
||||
it('should use the last entry\'s address when URL-like specifiers parse to the same absolute URL', () => {
|
||||
expect(resolveUnderTest('/test')).toMatchURL('https://example.com/lib/test2.mjs');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,205 @@
|
|||
let log = [];
|
||||
|
||||
function expect_log(test, expected_log) {
|
||||
test.step_func_done(() => {
|
||||
const actual_log = log;
|
||||
log = [];
|
||||
assert_array_equals(actual_log, expected_log, 'fallback log');
|
||||
})();
|
||||
}
|
||||
|
||||
// Results of resolving a specifier using import maps.
|
||||
const Result = {
|
||||
// A built-in module (std:blank) is loaded.
|
||||
BUILTIN: "builtin",
|
||||
|
||||
// A failure considered as a fetch error in a module script tree.
|
||||
// <script>'s error event is fired.
|
||||
FETCH_ERROR: "fetch_error",
|
||||
|
||||
// A failure considered as a parse error in a module script tree.
|
||||
// Window's error event is fired.
|
||||
PARSE_ERROR: "parse_error",
|
||||
|
||||
// The specifier is considered as a relative or absolute URL.
|
||||
// Specifier Expected log
|
||||
// ------------------------- ----------------------
|
||||
// ...?name=foo log:foo
|
||||
// data:...log('foo') foo
|
||||
// Others, e.g. @std/blank relative:@std/blank
|
||||
// ------------------------- ----------------------
|
||||
// (The last case assumes a file `@std/blank` that logs `relative:@std/blank`
|
||||
// exists)
|
||||
URL: "URL",
|
||||
};
|
||||
|
||||
const Handler = {
|
||||
// Handlers for <script> element cases.
|
||||
// Note that on a parse error both WindowErrorEvent and ScriptLoadEvent are
|
||||
// called.
|
||||
ScriptLoadEvent: "<script> element's load event handler",
|
||||
ScriptErrorEvent: "<script> element's error event handler",
|
||||
WindowErrorEvent: "window's error event handler",
|
||||
|
||||
// Handlers for dynamic imports.
|
||||
DynamicImportResolve: "dynamic import resolve",
|
||||
DynamicImportReject: "dynamic import reject",
|
||||
};
|
||||
|
||||
// Returns a map with Handler.* as the keys.
|
||||
function getHandlers(t, specifier, expected) {
|
||||
let handlers = {};
|
||||
handlers[Handler.ScriptLoadEvent] = t.unreached_func("Shouldn't load");
|
||||
handlers[Handler.ScriptErrorEvent] =
|
||||
t.unreached_func("script's error event shouldn't be fired");
|
||||
handlers[Handler.WindowErrorEvent] =
|
||||
t.unreached_func("window's error event shouldn't be fired");
|
||||
handlers[Handler.DynamicImportResolve] =
|
||||
t.unreached_func("dynamic import promise shouldn't be resolved");
|
||||
handlers[Handler.DynamicImportReject] =
|
||||
t.unreached_func("dynamic import promise shouldn't be rejected");
|
||||
|
||||
if (expected === Result.FETCH_ERROR) {
|
||||
handlers[Handler.ScriptErrorEvent] = () => expect_log(t, []);
|
||||
handlers[Handler.DynamicImportReject] = () => expect_log(t, []);
|
||||
} else if (expected === Result.PARSE_ERROR) {
|
||||
let error_occurred = false;
|
||||
handlers[Handler.WindowErrorEvent] = () => { error_occurred = true; };
|
||||
handlers[Handler.ScriptLoadEvent] = t.step_func(() => {
|
||||
// Even if a parse error occurs, load event is fired (after
|
||||
// window.onerror is called), so trigger the load handler only if
|
||||
// there was no previous window.onerror call.
|
||||
assert_true(error_occurred, "window.onerror should be fired");
|
||||
expect_log(t, []);
|
||||
});
|
||||
handlers[Handler.DynamicImportReject] = t.step_func(() => {
|
||||
assert_false(error_occurred,
|
||||
"window.onerror shouldn't be fired for dynamic imports");
|
||||
expect_log(t, []);
|
||||
});
|
||||
} else {
|
||||
let expected_log;
|
||||
if (expected === Result.BUILTIN) {
|
||||
expected_log = [];
|
||||
} else if (expected === Result.URL) {
|
||||
const match_data_url = specifier.match(/data:.*log\.push\('(.*)'\)/);
|
||||
const match_log_js = specifier.match(/name=(.*)/);
|
||||
if (match_data_url) {
|
||||
expected_log = [match_data_url[1]];
|
||||
} else if (match_log_js) {
|
||||
expected_log = ["log:" + match_log_js[1]];
|
||||
} else {
|
||||
expected_log = ["relative:" + specifier];
|
||||
}
|
||||
} else {
|
||||
expected_log = [expected];
|
||||
}
|
||||
handlers[Handler.ScriptLoadEvent] = () => expect_log(t, expected_log);
|
||||
handlers[Handler.DynamicImportResolve] = () => expect_log(t, expected_log);
|
||||
}
|
||||
return handlers;
|
||||
}
|
||||
|
||||
// Creates an <iframe> and run a test inside the <iframe>
|
||||
// to separate the module maps and import maps in each test.
|
||||
function testInIframe(importMapString, importMapBaseURL, testScript) {
|
||||
const iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
if (!importMapBaseURL) {
|
||||
importMapBaseURL = document.baseURI;
|
||||
}
|
||||
let content = `
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/import-maps/resources/test-helper.js"></script>
|
||||
<base href="${importMapBaseURL}">
|
||||
`;
|
||||
if (importMapString) {
|
||||
content += `
|
||||
<script type="importmap">
|
||||
${importMapString}
|
||||
</sc` + `ript>
|
||||
`;
|
||||
}
|
||||
content += `
|
||||
<body>
|
||||
<script>
|
||||
setup({ allow_uncaught_exception: true });
|
||||
${testScript}
|
||||
</sc` + `ript>
|
||||
`;
|
||||
iframe.contentDocument.write(content);
|
||||
iframe.contentDocument.close();
|
||||
fetch_tests_from_window(iframe.contentWindow);
|
||||
}
|
||||
|
||||
function testScriptElement(importMapString, importMapBaseURL, specifier, expected, type) {
|
||||
testInIframe(importMapString, importMapBaseURL, `
|
||||
const t = async_test("${specifier}: <script src type=${type}>");
|
||||
const handlers = getHandlers(t, "${specifier}", "${expected}");
|
||||
const script = document.createElement("script");
|
||||
script.setAttribute("type", "${type}");
|
||||
script.setAttribute("src", "${specifier}");
|
||||
script.addEventListener("load", handlers[Handler.ScriptLoadEvent]);
|
||||
script.addEventListener("error", handlers[Handler.ScriptErrorEvent]);
|
||||
window.addEventListener("error", handlers[Handler.WindowErrorEvent]);
|
||||
document.body.appendChild(script);
|
||||
`);
|
||||
}
|
||||
|
||||
function testStaticImport(importMapString, importMapBaseURL, specifier, expected) {
|
||||
testInIframe(importMapString, importMapBaseURL, `
|
||||
const t = async_test("${specifier}: static import");
|
||||
const handlers = getHandlers(t, "${specifier}", "${expected}");
|
||||
const script = document.createElement("script");
|
||||
script.setAttribute("type", "module");
|
||||
script.setAttribute("src",
|
||||
"/import-maps/static-import.js?pipe=sub(none)&url=" +
|
||||
encodeURIComponent("${specifier}"));
|
||||
script.addEventListener("load", handlers[Handler.ScriptLoadEvent]);
|
||||
script.addEventListener("error", handlers[Handler.ScriptErrorEvent]);
|
||||
window.addEventListener("error", handlers[Handler.WindowErrorEvent]);
|
||||
document.body.appendChild(script);
|
||||
`);
|
||||
}
|
||||
|
||||
function testDynamicImport(importMapString, importMapBaseURL, specifier, expected, type) {
|
||||
testInIframe(importMapString, importMapBaseURL, `
|
||||
const t = async_test("${specifier}: dynamic import (from ${type})");
|
||||
const handlers = getHandlers(t, "${specifier}", "${expected}");
|
||||
const script = document.createElement("script");
|
||||
script.setAttribute("type", "${type}");
|
||||
script.innerText =
|
||||
"import(\\"${specifier}\\")" +
|
||||
".then(handlers[Handler.DynamicImportResolve], " +
|
||||
"handlers[Handler.DynamicImportReject]);";
|
||||
script.addEventListener("error",
|
||||
t.unreached_func("top-level inline script shouldn't error"));
|
||||
document.body.appendChild(script);
|
||||
`);
|
||||
}
|
||||
|
||||
function doTests(importMapString, importMapBaseURL, tests) {
|
||||
window.addEventListener("load", () => {
|
||||
for (const specifier in tests) {
|
||||
// <script src> (module scripts)
|
||||
testScriptElement(importMapString, importMapBaseURL, specifier,
|
||||
tests[specifier][0], "module");
|
||||
|
||||
// <script src> (classic scripts)
|
||||
testScriptElement(importMapString, importMapBaseURL, specifier,
|
||||
tests[specifier][1], "text/javascript");
|
||||
|
||||
// static imports.
|
||||
testStaticImport(importMapString, importMapBaseURL, specifier,
|
||||
tests[specifier][2]);
|
||||
|
||||
// dynamic imports from a module script.
|
||||
testDynamicImport(importMapString, importMapBaseURL, specifier,
|
||||
tests[specifier][3], "module");
|
||||
|
||||
// dynamic imports from a classic script.
|
||||
testDynamicImport(importMapString, importMapBaseURL, specifier,
|
||||
tests[specifier][3], "text/javascript");
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
import "{{GET[url]}}";
|
Loading…
Add table
Add a link
Reference in a new issue