blob: b6a66866ea6a5537922ae200a3bb01f0c41d53db [file] [log] [blame]
promise_test(async () => {
const module = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/root.js');
assert_equals(module.result, 'OK');
}, 'Subresource loading with WebBundle');
promise_test(async () => {
const response = await fetch('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/root.js');
const text = await response.text();
assert_equals(text, 'export * from \'./submodule.js\';\n');
}, 'Subresource loading with WebBundle (Fetch API)');
promise_test(t => {
const url =
'/common/redirect.py?location=https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/root.js';
return promise_rejects_js(t, TypeError, import(url));
}, 'Subresource loading with WebBundle shouldn\'t affect redirect');
promise_test(async () => {
const element = createWebBundleElement(
'../resources/wbn/dynamic1-b2.wbn',
[
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js',
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource2.js',
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource4.js'
]);
document.body.appendChild(element);
const module = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module.result, 'resource1 from dynamic1.wbn');
document.body.removeChild(element);
}, 'Subresource loading from a b2 bundle');
promise_test(async () => {
const classic_script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/classic_script.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1-b2.wbn',
[classic_script_url]);
document.body.appendChild(element);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic1.wbn');
changeWebBundleUrl(element, '../resources/wbn/dynamic2-b2.wbn');
// Loading the classic script should not reuse the previously loaded
// script. So in this case, the script must be loaded from dynamic2-b2.wbn.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
document.body.removeChild(element);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
}, 'Dynamically loading classic script from a \'b2\' web bundle with resources attribute');
promise_test(async () => {
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js',
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource2.js',
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource4.js'
]);
document.body.appendChild(element);
const module = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module.result, 'resource1 from dynamic1.wbn');
changeWebBundleUrl(element, '../resources/wbn/dynamic2-b2.wbn');
const module2 = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource2.js');
assert_equals(module2.result, 'resource2 from dynamic2.wbn');
// A resource not specified in the resources attribute, but in the bundle.
const module3 = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource3.js');
assert_equals(module3.result, 'resource3 from network');
document.body.removeChild(element);
const module4 = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource4.js');
assert_equals(module4.result, 'resource4 from network');
// Module scripts are stored to the Document's module map once loaded.
// So import()ing the same module script will reuse the previously loaded
// script.
const module_second = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module_second.result, 'resource1 from dynamic1.wbn');
}, 'Dynamically adding / updating / removing the webbundle element.');
promise_test(async () => {
const classic_script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/classic_script.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[classic_script_url]);
document.body.appendChild(element);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic1.wbn');
changeWebBundleUrl(element, '../resources/wbn/dynamic2-b2.wbn');
// Loading the classic script should not reuse the previously loaded
// script. So in this case, the script must be loaded from dynamic2.wbn.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
document.body.removeChild(element);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
}, 'Dynamically loading classic script from web bundle');
promise_test(async (t) => {
// To avoid caching mechanism, this test is using fetch() API with
// { cache: 'no-store' } to load the resource.
const classic_script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/classic_script.js';
assert_equals(
await (await fetch(classic_script_url)).text(),
'window.report_result(\'classic script from network\');\n');
const element1 = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[classic_script_url]);
document.body.appendChild(element1);
t.add_cleanup(() => {
if (element1.parentElement)
element1.parentElement.removeChild(element1);
});
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic1.wbn\');\n');
const element2 = createWebBundleElement(
'../resources/wbn/dynamic2.wbn',
[classic_script_url]);
document.body.appendChild(element2);
t.add_cleanup(() => {
if (element2.parentElement)
element2.parentElement.removeChild(element2);
});
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic2.wbn\');\n');
document.body.removeChild(element2);
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic1.wbn\');\n');
document.body.removeChild(element1);
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from network\');\n');
}, 'Multiple web bundle elements. The last added element must be refered.');
promise_test(async () => {
const classic_script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/classic_script.js';
const scope = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/';
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[],
{scopes: [scope]});
document.body.appendChild(element);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic1.wbn');
changeWebBundleUrl(element, '../resources/wbn/dynamic2.wbn');
// Loading the classic script should not reuse the previously loaded
// script. So in this case, the script must be loaded from dynamic2.wbn.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
// Changes the scope not to hit the classic_script.js.
changeWebBundleScopes(element, [scope + 'dummy']);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
// Adds the scope to hit the classic_script.js.
changeWebBundleScopes(element, [scope + 'dummy', scope + 'classic_']);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
document.body.removeChild(element);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
}, 'Dynamically loading classic script from web bundle with scopes');
promise_test(() => {
return addWebBundleElementAndWaitForLoad(
'../resources/wbn/dynamic1.wbn?test-event',
/*resources=*/[],
{crossOrigin: undefined});
}, 'The webbundle element fires a load event on load success');
promise_test((t) => {
return addWebBundleElementAndWaitForError(
'../resources/wbn/nonexistent.wbn',
/*resources=*/[],
{crossOrigin: undefined});
}, 'The webbundle element fires an error event on load failure');
promise_test(async () => {
const module_script_url = 'https://www1.{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1-crossorigin.wbn',
[module_script_url]);
document.body.appendChild(element);
const module = await import(module_script_url);
assert_equals(module.result, 'resource1 from network');
}, 'Subresource URL must be same-origin with bundle URL');
promise_test(async () => {
const module_script_url = 'https://www1.{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1-crossorigin-b2.wbn',
[module_script_url]);
document.body.appendChild(element);
const module = await import(module_script_url);
assert_equals(module.result, 'resource1 from network');
}, 'Subresource URL must be same-origin with bundle URL (for \'b2\' bundles too)');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid.wbn',
[url]);
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with urn:uuid: URL with resources attribute');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid.wbn',
[],
{scopes: ['urn:uuid:']});
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with urn:uuid: URL with scopes attribute');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid-b2.wbn',
[url]);
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with urn:uuid: URL of a \'b2\' bundle with resources attribute');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid-b2.wbn',
[],
{scopes: ['urn:uuid:']});
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with urn:uuid: URL of a \'b2\' bundle with scopes attribute');
promise_test(async () => {
const wbn_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/subresource.wbn?test-resources-update';
const resource_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/submodule.js';
const element = await addWebBundleElementAndWaitForLoad(wbn_url, /*resources=*/[]);
changeWebBundleResources(element, [resource_url]);
const resp = await fetch(resource_url, { cache: 'no-store' });
assert_true(resp.ok);
assert_equals(performance.getEntriesByName(wbn_url).length, 1);
document.body.removeChild(element);
}, 'Updating resource attribute should not reload the bundle');
async function loadScriptAndWaitReport(script_url) {
const result_promise = new Promise((resolve) => {
// This function will be called from script.js
window.report_result = resolve;
});
const script = document.createElement('script');
script.src = script_url;
document.body.appendChild(script);
return result_promise;
}