tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

modulepreload.html (15046B)


      1 <!DOCTYPE html>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 <script src="/common/get-host-info.sub.js"></script>
      5 <body>
      6 <script>
      7 host_info = get_host_info();
      8 
      9 function verifyNumberOfDownloads(url, number, allowTransferSizeOfZero = false) {
     10    var numDownloads = 0;
     11    let absoluteURL = new URL(url, location.href).href;
     12    performance.getEntriesByName(absoluteURL).forEach(entry => {
     13        if (entry.transferSize > 0 || allowTransferSizeOfZero) {
     14            numDownloads++;
     15        }
     16    });
     17    assert_equals(numDownloads, number, url);
     18 }
     19 
     20 function attachAndWaitForLoad(element) {
     21    return new Promise((resolve, reject) => {
     22        element.onload = resolve;
     23        element.onerror = reject;
     24        document.body.appendChild(element);
     25    });
     26 }
     27 
     28 function attachAndWaitForError(element) {
     29    return new Promise((resolve, reject) => {
     30        element.onload = reject;
     31        element.onerror = resolve;
     32        document.body.appendChild(element);
     33    });
     34 }
     35 
     36 function attachAndWaitForTimeout(element, t) {
     37    return new Promise((resolve, reject) => {
     38        element.onload = reject;
     39        element.onerror = reject;
     40        t.step_timeout(resolve, 1000);
     41        document.body.appendChild(element);
     42    });
     43 }
     44 
     45 promise_test(function(t) {
     46    var link = document.createElement('link');
     47    link.rel = 'modulepreload';
     48    link.href = 'resources/dummy.js?unique';
     49    return attachAndWaitForLoad(link).then(() => {
     50        verifyNumberOfDownloads('resources/dummy.js?unique', 1);
     51 
     52        // Verify that <script> doesn't fetch the module again.
     53        var script = document.createElement('script');
     54        script.type = 'module';
     55        script.src = 'resources/dummy.js?unique';
     56        return attachAndWaitForLoad(script);
     57    }).then(() => {
     58        verifyNumberOfDownloads('resources/dummy.js?unique', 1);
     59    });
     60 }, 'link rel=modulepreload');
     61 
     62 /**
     63 * Begin tests to ensure crossorigin value behaves the same on
     64 * link rel=modulepreload as it does script elements.
     65 */
     66 promise_test(function(t) {
     67    document.cookie = 'same=1';
     68    var link = document.createElement('link');
     69    link.rel = 'modulepreload';
     70    link.crossOrigin = 'anonymous';
     71    link.href = 'resources/dummy.js?sameOriginAnonymous';
     72    return attachAndWaitForLoad(link).then(() => {
     73        verifyNumberOfDownloads('resources/dummy.js?sameOriginAnonymous', 1);
     74 
     75        // Verify that <script> doesn't fetch the module again.
     76        var script = document.createElement('script');
     77        script.type = 'module';
     78        script.crossOrigin = 'anonymous';
     79        script.src = 'resources/dummy.js?sameOriginAnonymous';
     80        return attachAndWaitForLoad(script);
     81    }).then(() => {
     82        verifyNumberOfDownloads('resources/dummy.js?sameOriginAnonymous', 1);
     83    });
     84 }, 'same-origin link rel=modulepreload crossorigin=anonymous');
     85 
     86 promise_test(function(t) {
     87    var link = document.createElement('link');
     88    link.rel = 'modulepreload';
     89    link.crossOrigin = 'use-credentials';
     90    link.href = 'resources/dummy.js?sameOriginUseCredentials';
     91    return attachAndWaitForLoad(link).then(() => {
     92        verifyNumberOfDownloads('resources/dummy.js?sameOriginUseCredentials', 1);
     93 
     94        // Verify that <script> doesn't fetch the module again.
     95        var script = document.createElement('script');
     96        script.type = 'module';
     97        script.crossOrigin = 'use-credentials';
     98        script.src = 'resources/dummy.js?sameOriginUseCredentials';
     99        return attachAndWaitForLoad(script);
    100    }).then(() => {
    101        verifyNumberOfDownloads('resources/dummy.js?sameOriginUseCredentials', 1);
    102    });
    103 }, 'same-origin link rel=modulepreload crossorigin=use-credentials');
    104 
    105 promise_test(function(t) {
    106    const setCookiePromise = fetch(
    107        `${host_info.HTTP_REMOTE_ORIGIN}/cookies/resources/set-cookie.py?name=cross&path=/preload/`,
    108        {
    109          mode: 'no-cors',
    110          credentials: 'include',
    111        });
    112 
    113    return setCookiePromise.then(() => {
    114        var link = document.createElement('link');
    115        link.rel = 'modulepreload';
    116        link.href = `${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginNone`;
    117        return attachAndWaitForLoad(link);
    118    }).then(() => {
    119        verifyNumberOfDownloads(`${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginNone`, 1, true);
    120 
    121        // Verify that <script> doesn't fetch the module again.
    122        var script = document.createElement('script');
    123        script.type = 'module';
    124        script.src = `${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginNone`;
    125        return attachAndWaitForLoad(script);
    126    }).then(() => {
    127        verifyNumberOfDownloads(`${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginNone`, 1, true);
    128    });
    129 }, 'cross-origin link rel=modulepreload');
    130 
    131 promise_test(function(t) {
    132    var link = document.createElement('link');
    133    link.rel = 'modulepreload';
    134    link.crossOrigin = 'anonymous';
    135    link.href = `${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginAnonymous`;
    136    return attachAndWaitForLoad(link).then(() => {
    137        verifyNumberOfDownloads(`${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginAnonymous`, 1, true);
    138 
    139        // Verify that <script> doesn't fetch the module again.
    140        var script = document.createElement('script');
    141        script.type = 'module';
    142        script.crossOrigin = 'anonymous';
    143        script.src = `${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginAnonymous`;
    144        return attachAndWaitForLoad(script);
    145    }).then(() => {
    146        verifyNumberOfDownloads(`${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginAnonymous`, 1, true);
    147    });
    148 }, 'cross-origin link rel=modulepreload crossorigin=anonymous');
    149 
    150 promise_test(function(t) {
    151    var link = document.createElement('link');
    152    link.rel = 'modulepreload';
    153    link.crossOrigin = 'use-credentials';
    154    link.href = `${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginUseCredentials`;
    155    return attachAndWaitForLoad(link).then(() => {
    156        verifyNumberOfDownloads(`${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginUseCredentials`, 1, true);
    157 
    158        // Verify that <script> doesn't fetch the module again.
    159        var script = document.createElement('script');
    160        script.type = 'module';
    161        script.crossOrigin = 'use-credentials';
    162        script.src = `${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginUseCredentials`;
    163        return attachAndWaitForLoad(script);
    164    }).then(() => {
    165        verifyNumberOfDownloads(`${host_info.HTTP_REMOTE_ORIGIN}/preload/resources/cross-origin-module.py?crossOriginUseCredentials`, 1, true);
    166    });
    167 }, 'cross-origin link rel=modulepreload crossorigin=use-credentials');
    168 /**
    169 * End link rel=modulepreload crossorigin attribute tests.
    170 */
    171 
    172 promise_test(function(t) {
    173    var link = document.createElement('link');
    174    link.rel = 'modulepreload';
    175    link.href = 'resources/module1.js?submodule';
    176    return attachAndWaitForLoad(link).then(() => {
    177        verifyNumberOfDownloads('resources/module1.js?submodule', 1);
    178        // The load event fires before (optional) submodules fetch.
    179        verifyNumberOfDownloads('resources/module2.js', 0);
    180 
    181        var script = document.createElement('script');
    182        script.type = 'module';
    183        script.src = 'resources/module1.js?submodule';
    184        return attachAndWaitForLoad(script);
    185    }).then(() => {
    186        verifyNumberOfDownloads('resources/module1.js?submodule', 1);
    187        verifyNumberOfDownloads('resources/module2.js', 1);
    188    });
    189 }, 'link rel=modulepreload with submodules');
    190 
    191 promise_test(function(t) {
    192    var link = document.createElement('link');
    193    link.rel = 'modulepreload';
    194    link.href = 'resources/syntax-error.js';
    195    return attachAndWaitForLoad(link);
    196 }, 'link rel=modulepreload for a module with syntax error');
    197 
    198 promise_test(function(t) {
    199    var link = document.createElement('link');
    200    link.rel = 'modulepreload';
    201    link.href = 'resources/not-exist.js';
    202    return attachAndWaitForError(link);
    203 }, 'link rel=modulepreload for a module with network error');
    204 
    205 promise_test(function(t) {
    206    var link = document.createElement('link');
    207    link.rel = 'modulepreload';
    208    link.href = null;
    209    return attachAndWaitForError(link);
    210 }, 'link rel=modulepreload with bad href attribute');
    211 
    212 promise_test(function(t) {
    213    var link = document.createElement('link');
    214    link.rel = 'modulepreload';
    215    link.href = 'resources/module1.js?as-script';
    216    link.as = 'script'
    217    return attachAndWaitForLoad(link);
    218 }, 'link rel=modulepreload as=script');
    219 
    220 promise_test(function(t) {
    221    var link = document.createElement('link');
    222    link.rel = 'modulepreload';
    223    link.href = 'resources/module1.js?as-image';
    224    link.as = 'image'
    225    return attachAndWaitForError(link);
    226 }, 'link rel=modulepreload with non-script-like as= value (image)');
    227 
    228 promise_test(function(t) {
    229    var link = document.createElement('link');
    230    link.rel = 'modulepreload';
    231    link.href = 'resources/module1.js?as-xslt';
    232    link.as = 'xslt'
    233    return attachAndWaitForError(link);
    234 }, 'link rel=modulepreload with non-script-like as= value (xslt)');
    235 
    236 promise_test(function(t) {
    237    var link = document.createElement('link');
    238    link.rel = 'modulepreload';
    239    link.href = 'resources/module1.js?integrity-match';
    240    link.integrity = 'sha256-+Ks3iNIiTq2ujlWhvB056cmXobrCFpU9hd60xZ1WCaA='
    241    return attachAndWaitForLoad(link);
    242 }, 'link rel=modulepreload with integrity match');
    243 
    244 promise_test(function(t) {
    245    var link = document.createElement('link');
    246    link.rel = 'modulepreload';
    247    link.href = 'resources/module1.mjs?integrity-match';
    248    link.integrity = 'sha256-+Ks3iNIiTq2ujlWhvB056cmXobrCFpU9hd60xZ1WCaA='
    249    return attachAndWaitForLoad(link);
    250 }, 'link rel=modulepreload with integrity match2');
    251 
    252 promise_test(function(t) {
    253    var link = document.createElement('link');
    254    link.rel = 'modulepreload';
    255    link.href = 'resources/module1.js?integrity-doesnotmatch';
    256    link.integrity = 'sha384-doesnotmatch'
    257    return attachAndWaitForError(link);
    258 }, 'link rel=modulepreload with integrity mismatch');
    259 
    260 promise_test(function(t) {
    261    var link = document.createElement('link');
    262    link.rel = 'modulepreload';
    263    link.href = 'resources/module1.mjs?integrity-doesnotmatch';
    264    link.integrity = 'sha256-dOxReWMnMSPfUvxEbBqIrjNh8ZN8n05j7h3JmhF8gQc='
    265    return attachAndWaitForError(link);
    266 }, 'link rel=modulepreload with integrity mismatch2');
    267 
    268 promise_test(function(t) {
    269    var link = document.createElement('link');
    270    link.rel = 'modulepreload';
    271    link.href = 'resources/module1.mjs?integrity-invalid';
    272    link.integrity = 'sha256-dOxReWMnMSPfUvxEbBqIrjNh8ZN8n05j7h3JmhF8gQc=%'
    273    return attachAndWaitForError(link);
    274 }, 'link rel=modulepreload with integrity mismatch3');
    275 
    276 promise_test(function(t) {
    277    var link1 = document.createElement('link');
    278    var link2 = document.createElement('link');
    279    link1.rel = 'modulepreload';
    280    link2.rel = 'modulepreload';
    281    link1.href = 'resources/module1.js?same-url';
    282    link2.href = 'resources/module1.js?same-url';
    283    return Promise.all([
    284        attachAndWaitForLoad(link1),
    285        attachAndWaitForLoad(link2),
    286    ]);
    287 }, 'multiple link rel=modulepreload with same href');
    288 
    289 promise_test(function(t) {
    290    var link1 = document.createElement('link');
    291    var link2 = document.createElement('link');
    292    link1.rel = 'modulepreload';
    293    link2.rel = 'modulepreload';
    294    link1.href = 'resources/module2.js?child-before';
    295    link2.href = 'resources/module1.js?child-before';
    296    return attachAndWaitForLoad(link1)
    297        .then(() => attachAndWaitForLoad(link2))
    298        .then(() => new Promise(r => t.step_timeout(r, 1000)))
    299        .then(() => {
    300            verifyNumberOfDownloads('resources/module2.js?child-before', 1);
    301        });
    302 
    303 }, 'multiple link rel=modulepreload with child module before parent');
    304 
    305 promise_test(function(t) {
    306    var link = document.createElement('link');
    307    link.rel = 'modulepreload';
    308    link.href = 'resources/module1.mjs?matching-media';
    309    link.media = 'all';
    310    return attachAndWaitForLoad(link);
    311 }, 'link rel=modulepreload with matching media');
    312 
    313 promise_test(function(t) {
    314    var link = document.createElement('link');
    315    link.rel = 'modulepreload';
    316    link.href = 'resources/module1.mjs?non-matching-media';
    317    link.media = 'not all';
    318    return attachAndWaitForTimeout(link, t);
    319 }, 'link rel=modulepreload with non-matching media');
    320 
    321 promise_test(function(t) {
    322    var link = document.createElement('link');
    323    link.rel = 'modulepreload';
    324    link.href = 'resources/module1.mjs?empty-media';
    325    link.media = '';
    326    return attachAndWaitForLoad(link);
    327 }, 'link rel=modulepreload with empty media');
    328 
    329 promise_test(function(t) {
    330    var link = document.createElement('link');
    331    link.rel = 'modulepreload';
    332    link.href = '';
    333    return attachAndWaitForTimeout(link, t);
    334 }, 'link rel=modulepreload with empty href');
    335 
    336 promise_test(function(t) {
    337    var link = document.createElement('link');
    338    link.rel = 'modulepreload';
    339    link.href = '';
    340    link.as = 'fetch';
    341    return attachAndWaitForTimeout(link, t);
    342 }, 'link rel=modulepreload with empty href and invalid as= value');
    343 
    344 promise_test(function(t) {
    345    var link = document.createElement('link');
    346    var script = document.createElement('script');
    347    link.rel = 'modulepreload';
    348    script.type = 'module';
    349    link.href = 'resources/module1.mjs?non-matching-crossorigin';
    350    script.src = link.href;
    351    script.crossOrigin = 'anonymous';
    352    document.body.append(link);
    353    return attachAndWaitForLoad(script);
    354 }, 'link rel=modulepreload and script with non-matching crossorigin values');
    355 
    356 promise_test(function(t) {
    357    var link = document.createElement('link');
    358    var script = document.createElement('script');
    359    link.rel = 'modulepreload';
    360    script.type = 'module';
    361    link.href = 'resources/module1.mjs?non-matching-crossorigin';
    362    script.src = link.href;
    363    link.crossOrigin = 'anonymous';
    364    script.crossOrigin = 'use-credentials';
    365    document.body.append(link);
    366    return attachAndWaitForLoad(script);
    367 }, 'link rel=modulepreload and script with non-matching crossorigin values2');
    368 
    369 promise_test(function(t) {
    370    var link = document.createElement('link');
    371    var moduleScript = document.createElement('script');
    372    var classicScript = document.createElement('script');
    373    link.rel = 'modulepreload';
    374    moduleScript.type = 'module';
    375    link.href = 'resources/dummy.js?non-module script';
    376    classicScript.src = link.href;
    377    moduleScript.src = link.href;
    378    document.body.append(link);
    379    document.body.append(classicScript);
    380    return attachAndWaitForLoad(moduleScript);
    381 }, 'link rel=modulepreload and non-module script');
    382 </script>
    383 </body>