-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce <script>-based API for subresource loading with Web Bundles. See the design doc [1] for the motivation of switching from <link>-based API to <script>-based API. The explainer [2] was already updated to use <script>-based API. This feature is guarded by `SubresourceWebBundles` flag. We eventually drop the <link rel=webbundle> support and remove the <link>-based API code once we can confirm <script>-based API can be used as a replacement of <link>-based API. This CL should be considered as the first step to switch to <script>-based API. There are still gaps between <link>-based API and <script>-based API, which will be addressed later [3]. This CL intentionally adds a very minimum test for <script>-based API because there are already WPT tests for <script type=webbundle>. They all have been marked as [ SKIP ] in TestExpectations until now. Now some of them are passing after this CL. We'll make the remaining tests pass in follow-up CLs, and also add tests which are specific to <script>-based API as necessary. These efforts should be tracked by crbug.com/1245166. [1]: https://docs.google.com/document/d/1q_SodTcLuwya4cXt1gIRaVrkiaBfwWyPvkY1fqRKkgM/edit?usp=sharing&resourcekey=0-dqrFOGVCYsg8WRZ4RFgwuw [2]: https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md [3]: WICG/webpackage#670 Bug: 1245166 Change-Id: I5109b6e692baf10fd1d8a31a31d93176d4dc4ad2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3128843 Commit-Queue: Hayato Ito <hayato@chromium.org> Reviewed-by: Tsuyoshi Horo <horo@chromium.org> Reviewed-by: Kunihiko Sakamoto <ksakamoto@chromium.org> Reviewed-by: Hiroshige Hayashizaki <hiroshige@chromium.org> Reviewed-by: Kouhei Ueno <kouhei@chromium.org> Cr-Commit-Position: refs/heads/main@{#933346}
- Loading branch information
1 parent
aea6e4f
commit 47f30fc
Showing
2 changed files
with
215 additions
and
0 deletions.
There are no files selected for viewing
199 changes: 199 additions & 0 deletions
199
web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
<!DOCTYPE html> | ||
<title>script type="webbundle" reuses webbundle 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> | ||
|
||
<body> | ||
<script> | ||
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = "script"; | ||
setup(() => { | ||
assert_true(HTMLScriptElement.supports("webbundle")); | ||
}); | ||
|
||
const wbn_url = "../resources/wbn/subresource.wbn"; | ||
const resource1 = "../resources/wbn/root.js"; | ||
const resource2 = "../resources/wbn/submodule.js"; | ||
|
||
let script1; | ||
let script2; | ||
|
||
function cleanUp() { | ||
if (script1) { | ||
script1.remove(); | ||
} | ||
if (script2) { | ||
script2.remove(); | ||
} | ||
} | ||
|
||
async function assertResource1CanBeFetched() { | ||
const response = await fetch(resource1); | ||
const text = await response.text(); | ||
assert_equals(text, "export * from './submodule.js';\n"); | ||
} | ||
|
||
async function assertResource1CanNotBeFetched() { | ||
const response = await fetch(resource1); | ||
assert_equals(response.status, 404); | ||
} | ||
|
||
async function assertResource2CanBeFetched() { | ||
const response = await fetch(resource2); | ||
const text = await response.text(); | ||
assert_equals(text, "export const result = 'OK';\n"); | ||
} | ||
|
||
function createScriptWebBundle1() { | ||
return createWebBundleElement(wbn_url, /*resources=*/ [resource1]); | ||
} | ||
|
||
function createScriptWebBundle2() { | ||
return createWebBundleElement(wbn_url, /*resources=*/ [resource2]); | ||
} | ||
|
||
async function appendScriptWebBundle1AndFetchResource1() { | ||
clearWebBundleFetchCount(); | ||
script1 = createScriptWebBundle1(); | ||
document.body.append(script1); | ||
await assertResource1CanBeFetched(); | ||
assert_equals(webBundleFetchCount(), 1); | ||
} | ||
|
||
function clearWebBundleFetchCount() { | ||
performance.clearResourceTimings(); | ||
} | ||
|
||
function webBundleFetchCount() { | ||
return performance | ||
.getEntriesByType("resource") | ||
.filter((e) => e.name.endsWith("subresource.wbn")).length; | ||
} | ||
|
||
promise_test(async (t) => { | ||
t.add_cleanup(cleanUp); | ||
await appendScriptWebBundle1AndFetchResource1(); | ||
clearWebBundleFetchCount(); | ||
|
||
// Append script2 without removing script1. | ||
// script2 should fetch the wbn again. | ||
script2 = createScriptWebBundle2(); | ||
document.body.appendChild(script2); | ||
|
||
await assertResource1CanBeFetched() | ||
await assertResource2CanBeFetched(); | ||
assert_equals(webBundleFetchCount(), 1); | ||
}, "A webbundle should be fetched again when new script element is appended."); | ||
|
||
promise_test(async (t) => { | ||
t.add_cleanup(cleanUp); | ||
await appendScriptWebBundle1AndFetchResource1(); | ||
clearWebBundleFetchCount(); | ||
|
||
// Remove script1, then append script2 | ||
// script2 should reuse webbundle resources. | ||
script1.remove(); | ||
script2 = createScriptWebBundle2(); | ||
document.body.append(script2); | ||
|
||
await assertResource1CanNotBeFetched(); | ||
await assertResource2CanBeFetched(); | ||
assert_equals(webBundleFetchCount(), 0); | ||
}, "'remove(), then append()' should reuse webbundle resources"); | ||
|
||
promise_test(async (t) => { | ||
t.add_cleanup(cleanUp); | ||
await appendScriptWebBundle1AndFetchResource1(); | ||
clearWebBundleFetchCount(); | ||
|
||
// Remove script1, then append the removed one. | ||
script1.remove(); | ||
document.body.append(script1); | ||
|
||
await assertResource1CanNotBeFetched(); | ||
assert_equals(webBundleFetchCount(), 0); | ||
}, "'remove(), then append()' for the same element should reuse webbundle resources"); | ||
|
||
promise_test(async (t) => { | ||
t.add_cleanup(cleanUp); | ||
await appendScriptWebBundle1AndFetchResource1(); | ||
clearWebBundleFetchCount(); | ||
|
||
// Multiple 'remove(), then append()' for the same element. | ||
script1.remove(); | ||
document.body.append(script1); | ||
|
||
script1.remove(); | ||
document.body.append(script1); | ||
|
||
await assertResource1CanNotBeFetched(); | ||
assert_equals(webBundleFetchCount(), 0); | ||
}, "Multiple 'remove(), then append()' for the same element should reuse webbundle resources"); | ||
|
||
|
||
promise_test(async (t) => { | ||
t.add_cleanup(cleanUp); | ||
await appendScriptWebBundle1AndFetchResource1(); | ||
clearWebBundleFetchCount(); | ||
|
||
// Remove script1. | ||
script1.remove(); | ||
|
||
// Then append script2 in a separet task. | ||
await new Promise(resolve => t.step_timeout(resolve, 0)); | ||
script2 = createScriptWebBundle2(); | ||
document.body.append(script2); | ||
|
||
await assertResource1CanNotBeFetched(); | ||
await assertResource2CanBeFetched(); | ||
assert_equals(webBundleFetchCount(), 1); | ||
}, "'remove(), then append() in a separate task' should not reuse webbundle resources"); | ||
|
||
|
||
promise_test(async (t) => { | ||
t.add_cleanup(cleanUp); | ||
await appendScriptWebBundle1AndFetchResource1(); | ||
clearWebBundleFetchCount(); | ||
|
||
// Use replaceWith() to replace script1 with script2. | ||
// script2 should reuse webbundle resources. | ||
script2 = createScriptWebBundle2(); | ||
script1.replaceWith(script2); | ||
|
||
await assertResource1CanNotBeFetched(); | ||
await assertResource2CanBeFetched(); | ||
|
||
assert_equals(webBundleFetchCount(), 0); | ||
}, "replaceWith() should reuse webbundle resources."); | ||
|
||
promise_test(async (t) => { | ||
t.add_cleanup(cleanUp); | ||
await appendScriptWebBundle1AndFetchResource1(); | ||
clearWebBundleFetchCount(); | ||
|
||
// Move script1 to another document. Then append script2. | ||
// script2 should reuse webbundle resources. | ||
const another_document = new Document(); | ||
another_document.append(script1); | ||
script2 = createScriptWebBundle2(); | ||
document.body.append(script2); | ||
|
||
await assertResource1CanNotBeFetched(); | ||
await assertResource2CanBeFetched(); | ||
|
||
assert_equals(webBundleFetchCount(), 0); | ||
|
||
// TODO: Test the following cases: | ||
// - The resources are not loaded from the webbundle in the new Document | ||
// (Probably better to use a <iframe>.contentDocument) | ||
// - Even if we move the script element back to the original Document, | ||
// even immediately, the resources are not loaded from the webbundle in the | ||
// original Document. | ||
}, "append() should reuse webbundle resoruces even if the old script was moved to another document."); | ||
|
||
</script> | ||
</body> |
16 changes: 16 additions & 0 deletions
16
web-bundle/subresource-loading/script-supports-webbundle.https.tentative.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<DOCTYPE html> | ||
<html> | ||
<title>HTMLScriptElement.supports webbundle</title> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script> | ||
test(() => { | ||
assert_true(HTMLScriptElement.supports('webbundle')); | ||
}, 'HTMLScriptElement.supports returns true for \'webbundle\''); | ||
|
||
test(() => { | ||
assert_false(HTMLScriptElement.supports(' webbundle')); | ||
assert_false(HTMLScriptElement.supports('webbundle ')); | ||
assert_false(HTMLScriptElement.supports('WEBBUNDLE')); | ||
}, 'HTMLScriptElement.supports returns false for unsupported types'); | ||
</script> |