tor-browser

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

not-as-classic-script.html (5703B)


      1 <!DOCTYPE html>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 
      5 <script>
      6 setup({allow_uncaught_exception : true});
      7 
      8 const t_parse = async_test("Import maps shouldn't be parsed as scripts");
      9 const t_already_started = async_test("The Already Started flag is passed through cloneNode");
     10 const t_evaluate = async_test("Import maps shouldn't be executed as scripts");
     11 const t_external = async_test(
     12   "External import maps shouldn't be executed as scripts");
     13 const t_change_type = async_test(
     14   "Import maps shouldn't be executed as scripts after changing type");
     15 
     16 const parseErrorHandler = event => {
     17  event.preventDefault();
     18  t_parse.unreached_func("An import map is parsed as a classic script")();
     19 };
     20 
     21 window.addEventListener("error", parseErrorHandler, {once: true});
     22 </script>
     23 
     24 <!-- This import map causes a parse error when parsed as a classic script. -->
     25 <script type="importmap">
     26 {
     27  "imports": {
     28  }
     29 }
     30 </script>
     31 
     32 <script>
     33 window.removeEventListener("error", parseErrorHandler);
     34 t_parse.done();
     35 
     36 const alreadyStartedErrorHandler = event => {
     37  event.preventDefault();
     38  t_already_started.unreached_func("An import map is evaluated as a classic script")();
     39 };
     40 
     41 window.addEventListener("error", alreadyStartedErrorHandler, {once: true});
     42 </script>
     43 
     44 <script>
     45 // Once Already Started is true on a classic script, it cannot be
     46 // converted into an import map.
     47 const dynamicScriptClassic = document.createElement("script");
     48 dynamicScriptClassic.type = "text/javascript";
     49 dynamicScriptClassic.innerText = "t_already_started.step(function() { assert_true(true, 'Classic script connected dynamically.');});";
     50 
     51 // Inserting a <script> with contents sets Already Started to true.
     52 document.head.appendChild(dynamicScriptClassic);
     53 document.head.removeChild(dynamicScriptClassic);
     54 
     55 // The existing innerText would be a parse error if parsed as an import
     56 // map, but is valid as a classic script.
     57 dynamicScriptClassic.type = "importmap";
     58 document.head.appendChild(dynamicScriptClassic);
     59 
     60 // The Already Started flag on a script is persisted upon cloning, so
     61 // the clone won't be parsed as an import map even though its `type`
     62 // was set to "importmap" when it was connected.
     63 const clonedClassicScript = dynamicScriptClassic.cloneNode(/*deep=*/true);
     64 t_already_started.step(function() {
     65  assert_equals(clonedClassicScript.type, "importmap");
     66  assert_equals(clonedClassicScript.innerText, dynamicScriptClassic.innerText);
     67 });
     68 document.head.appendChild(clonedClassicScript);
     69 
     70 // Creating an empty <script> tag does not set Already Started to true,
     71 // so the type can be changed later.
     72 const dynamicScriptEmpty = document.createElement("script");
     73 dynamicScriptEmpty.type = "text/javascript";
     74 document.head.appendChild(dynamicScriptEmpty);
     75 
     76 // The Already Started flag is copied onto clones, so the type can be
     77 // changed later.
     78 const clonedDynamicScriptEmpty = dynamicScriptEmpty.cloneNode(/*deep=*/true);
     79 t_already_started.step(function() {
     80  assert_equals(clonedDynamicScriptEmpty.type, "text/javascript");
     81 });
     82 clonedDynamicScriptEmpty.setAttribute("type", "importmap");
     83 t_already_started.step(function() {
     84  assert_equals(clonedDynamicScriptEmpty.type, "importmap");
     85 });
     86 
     87 // Since the contents are not empty, connecting the clone will set the
     88 // Already Started flag to true and lock the type into an import map.
     89 document.head.appendChild(clonedDynamicScriptEmpty);
     90 document.head.removeChild(clonedDynamicScriptEmpty);
     91 
     92 // This would cause a parse error when parsed as a classic script.
     93 clonedDynamicScriptEmpty.innerText = "{ \"imports\": {  } }";
     94 document.head.appendChild(clonedDynamicScriptEmpty);
     95 
     96 // The original element can have its contents set and will executed
     97 // as a classic script. Ensure this is executed by completing the test.
     98 dynamicScriptEmpty.innerText = "t_already_started.done();";
     99 document.head.appendChild(dynamicScriptEmpty);
    100 </script>
    101 
    102 <script>
    103 // Remove prior error handler, because the following import maps can
    104 // causes parse errors.
    105 window.removeEventListener("error", alreadyStartedErrorHandler);
    106 </script>
    107 
    108 <script>
    109 // A dynamically created import map isn't parsed as a classic script.
    110 const dynamicScript = document.createElement("script");
    111 dynamicScript.type = "importmap";
    112 t_evaluate.step(function() {
    113  assert_equals(dynamicScript.type, "importmap");
    114 });
    115 dynamicScript.innerText = "t_evaluate.unreached_func('A dynamically-created import map is evaluated')();";
    116 document.head.appendChild(dynamicScript);
    117 
    118 // Changing the type shouldn't execute script.
    119 dynamicScript.type = "text/javascript";
    120 t_evaluate.step(function() {
    121  assert_equals(dynamicScript.type, "text/javascript");
    122 });
    123 
    124 // Nor should removing it and re-inserting it.
    125 document.head.removeChild(dynamicScript);
    126 document.head.appendChild(dynamicScript);
    127 </script>
    128 
    129 <!-- Test the same with markup. -->
    130 <script type="importmap">
    131 t_evaluate.unreached_func("An import map is evaluated")();
    132 </script>
    133 
    134 <script>
    135 t_evaluate.done();
    136 </script>
    137 
    138 <script type="importmap" id="changeType">
    139 t_change_type.unreached_func("An import map is evaluated after changing type")();
    140 </script>
    141 
    142 <script>
    143 // Change the type from "importmap" to other valid values and ensure
    144 // script never executes.
    145 let changeType = document.getElementById("changeType");
    146 changeType.setAttribute("type", "text/javascript");
    147 changeType.setAttribute("type", "module");
    148 changeType.setAttribute("type", "");
    149 changeType.removeAttribute("type");
    150 t_change_type.done();
    151 </script>
    152 
    153 <!-- Import Maps do not execute external scripts. -->
    154 <script type="importmap" src="data:text/javascript,t_external.unreached_func('An external import map is evaluated')();"></script>
    155 
    156 <script>
    157 t_external.done();
    158 </script>