Skip to content

Commit

Permalink
<script type=webbundle>: Resolve a relative URL on the bundle's URL
Browse files Browse the repository at this point in the history
The explainer PR is: WICG/webpackage#700

One of the gaps between the Subresource Loading with WebBundles and
Bundle Preloading proposals is "how to resolve a relative URL of
resources". The former is using document's base URL, and the latter is
using the bundle's URL. We have to align.

At the era of <link>-based API, using a document's base URL might make
sense because `resources` are specified in the link element's
attribute.

Now we use <script>-based APIs, and `resources` is specified in JSON, so
we no longer have any strong reason to use a document's base URL.

See the spec discussion for details:
WICG/webpackage#699 (comment)

Bug: 1263807
Change-Id: Ic71f095589daa42db2d4649e2cf77212616b2f25
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3244822
Reviewed-by: Kunihiko Sakamoto <ksakamoto@chromium.org>
Commit-Queue: Hayato Ito <hayato@chromium.org>
Cr-Commit-Position: refs/heads/main@{#935333}
  • Loading branch information
hayatoito authored and Gabisampaio committed Nov 18, 2021
1 parent 690ae81 commit ea6e807
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 29 deletions.
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<title>Subresource loading using relative URLs in the 'resources'</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>

<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = "script";
setup(() => {
assert_true(HTMLScriptElement.supports("webbundle"));
});
</script>
<body>
<script>
let script;

function cleanUp() {
if (script) {
script.remove();
}
}

function createScriptWebBundle(resource) {
return createWebBundleElement(
"../resources/wbn/subresource.wbn",
/*resources=*/ [resource]
);
}

async function assertResourceCanBeFetched() {
const response = await fetch(`../resources/wbn/root.js`);
const text = await response.text();
assert_equals(text, "export * from './submodule.js';\n");
}

async function assertResourceNotFound() {
const response = await fetch(`../resources/wbn/root.js`);
const status = await response.status;
assert_equals(status, 404);
}

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("root.js");
document.body.append(script);
await assertResourceCanBeFetched();
}, "A relative URL, 'root.js', should be resolved on the bundle's URL");

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("./root.js");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use './root.js', starting with dot");

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("../wbn/root.js");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use '../wbn/root.js', starting with two dots");

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("/web-bundle/resources/wbn/root.js");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use '/web-bundle/resources/wbn/root.js', starting with slash");

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("unrelated-relative-url.js");
document.body.append(script);
await assertResourceNotFound();
}, "A resource should not be found");
</script>
</body>
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<title>
Subresource loading using relative URLs in the 'scopes'
</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>

<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = "script";
setup(() => {
assert_true(HTMLScriptElement.supports("webbundle"));
});
</script>
<body>
<script>
let script;

function cleanUp() {
if (script) {
script.remove();
}
}

function createScriptWebBundle(scope) {
return createWebBundleElement(
"../resources/wbn/relative-url.wbn",
/*resources=*/ [],
{ scopes: [scope] }
);
}

async function assertResourceCanBeFetched() {
const response = await fetch("../resources/wbn/relative-url/subdirectory-path.js");
const text = await response.text();
assert_equals(text, "scriptLoaded('subdirectory-path.js');");
}

async function assertResourceNotFound() {
const response = await fetch("../resources/wbn/relative-url/subdirectory-path.js");
const status = await response.status;
assert_equals(status, 404);
}

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("relative-url");
document.body.append(script);
await assertResourceCanBeFetched();
}, "A relative URL, 'relative-url', should be resolved on the bundle's URL");

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("./relative-url");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use './relative-url', starting with dot");

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("../wbn/relative-url");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use '../wbn/relative-url', starting with two dots");

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("/web-bundle/resources/wbn/relative-url");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use '/web-bundle/resources/wbn/relative-url', starting with slash");

promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("unrelated-scope");
document.body.append(script);
await assertResourceNotFound();
}, "A resource should not be found");
</script>
</body>
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>WebBundle subresource loading with relative URLs for static elements</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script type="webbundle">
{
"source": "../resources/wbn/static-element.wbn",
"resources": [
"static-element/resources/script.js"
],
"scopes": [
"static-element/scopes"
]
}
</script>
<script src="../resources/wbn/static-element/resources/script.js"></script>
<script src="../resources/wbn/static-element/scopes/script.js"></script>
<script src="../resources/wbn/static-element/out-of-scope/script.js"></script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
promise_test(async () => {
assert_equals(resources_script_result, 'loaded from webbundle');
assert_equals(scopes_script_result, 'loaded from webbundle');
assert_equals(out_of_scope_script_result, 'loaded from network');
}, 'Subresources from static elements should be loaded from web bundle.');
</script>
</body>

This file was deleted.

Expand Up @@ -16,8 +16,11 @@
});

const wbn_url = "../resources/wbn/subresource.wbn";
const resource1 = "../resources/wbn/root.js";
const resource2 = "../resources/wbn/submodule.js";
const resource1 = "root.js";
const resource2 = "submodule.js";

const resource1_url = `../resources/wbn/${resource1}`;
const resource2_url = `../resources/wbn/${resource2}`;

let script1;
let script2;
Expand All @@ -32,18 +35,18 @@
}

async function assertResource1CanBeFetched() {
const response = await fetch(resource1);
const response = await fetch(resource1_url);
const text = await response.text();
assert_equals(text, "export * from './submodule.js';\n");
}

async function assertResource1CanNotBeFetched() {
const response = await fetch(resource1);
const response = await fetch(resource1_url);
assert_equals(response.status, 404);
}

async function assertResource2CanBeFetched() {
const response = await fetch(resource2);
const response = await fetch(resource2_url);
const text = await response.text();
assert_equals(text, "export const result = 'OK';\n");
}
Expand Down

0 comments on commit ea6e807

Please sign in to comment.