tor-browser

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

declarative-shadow-dom-opt-in.html (6670B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>Declarative Shadow DOM</title>
      4 <link rel="author" href="mailto:masonf@chromium.org">
      5 <link rel="help" href="https://github.com/whatwg/dom/issues/831">
      6 <script src="/resources/testharness.js"></script>
      7 <script src="/resources/testharnessreport.js"></script>
      8 <script src='../../html/resources/common.js'></script>
      9 
     10 <body>
     11 <style>
     12  * { white-space: pre; }
     13  iframe { display:none; }
     14 </style>
     15 <div id=log></div>
     16 
     17 <div id=mainpage style="display:none">
     18  <div class=wrapper>
     19    <div class=host>
     20      <template shadowrootmode=open>
     21        <span class=content>Content</span>
     22      </template>
     23    </div>
     24  </div>
     25 </div>
     26 
     27 <script>
     28 const content = `
     29  <html><body>
     30  <div class=wrapper>
     31    <div class=host>
     32      <template shadowrootmode=open>
     33        <span class=content>Content</span>
     34      </template>
     35    </div>
     36  </div>
     37  </body></html>
     38 `;
     39 
     40 function assert_dsd(el,shouldHaveShadow) {
     41  const wrapper = el.querySelector('.wrapper');
     42  assert_true(!!wrapper,'Unable to find wrapper element');
     43  const host = wrapper.querySelector('.host');
     44  assert_true(!!host,'Unable to find host element');
     45  if (shouldHaveShadow) {
     46    assert_true(!!host.shadowRoot, 'Shadow root NOT FOUND.');
     47    assert_true(!!host.shadowRoot.querySelector('.content'),'Unable to locate content');
     48  } else {
     49    assert_true(!host.shadowRoot, 'Shadow root FOUND - none should be present.');
     50    const tmpl = host.querySelector('template');
     51    assert_true(!!tmpl, 'The template should be left as a <template> element');
     52    assert_equals(tmpl.getAttribute('shadowrootmode'),'open','The shadowrootmode attribute should still be present');
     53    assert_true(!!tmpl.content.querySelector('.content'),'Unable to locate content');
     54  }
     55 }
     56 
     57 test(() => {
     58  const div = document.getElementById('mainpage');
     59  assert_dsd(div,true);
     60 }, 'Non-fragment parsing needs no opt-in');
     61 
     62 const noChildElements = ['iframe','noscript','script','select','style','template','textarea','title','colgroup'];
     63 const elements = HTML5_ELEMENTS.filter(el => !noChildElements.includes(el));
     64 for (let elementName of elements) {
     65  var t = test(function() {
     66    const el1 = document.createElement(elementName);
     67    el1.innerHTML = content;
     68    assert_dsd(el1,false);
     69 
     70    const templateContent = `<template id=tmpl>${content}</template>`;
     71    const el2 = document.createElement('div');
     72    el2.innerHTML = templateContent;
     73    assert_dsd(el2.querySelector('#tmpl').content,false);
     74  }, `innerHTML on a <${elementName}>`);
     75 }
     76 
     77 test(() => {
     78  const temp = document.createElement('template');
     79  temp.innerHTML = content;
     80  assert_dsd(temp.content,false, 'innerHTML should not allow declarative shadow content');
     81 }, 'innerHTML on template');
     82 
     83 test(() => {
     84  const templateContent = `<template id=tmpl>${content}</template>`;
     85  const temp = document.createElement('template');
     86  temp.innerHTML = templateContent;
     87  assert_dsd(temp.content.querySelector('#tmpl').content,false);
     88 }, 'innerHTML on template, with nested template content');
     89 
     90 test(() => {
     91  const div = document.createElement('div');
     92  const shadow = div.attachShadow({mode: 'open'});
     93  shadow.innerHTML = content;
     94  assert_dsd(shadow,false);
     95 }, 'innerHTML on shadowRoot');
     96 
     97 test(() => {
     98  const parser = new DOMParser();
     99  let fragment = parser.parseFromString(content, 'text/html');
    100  assert_dsd(fragment.body,false);
    101  fragment = parser.parseFromString(content, 'text/html', {includeShadowRoots: false});
    102  assert_dsd(fragment.body,false);
    103  fragment = parser.parseFromString(content, 'text/html', {includeShadowRoots: true});
    104  assert_dsd(fragment.body,false);
    105 }, 'DOMParser (includeShadowRoots is historical)');
    106 
    107 test(() => {
    108  const doc = document.implementation.createHTMLDocument('');
    109  doc.body.innerHTML = content;
    110  assert_dsd(doc.body,false);
    111 }, 'createHTMLDocument with innerHTML - not supported');
    112 
    113 test(() => {
    114  const doc = document.implementation.createHTMLDocument('');
    115  let range = doc.createRange();
    116  range.selectNode(doc.body);
    117  let documentFragment = range.createContextualFragment(content);
    118  assert_dsd(documentFragment,false);
    119 }, 'createContextualFragment - not supported');
    120 
    121 async_test((t) => {
    122  let client = new XMLHttpRequest();
    123  client.addEventListener('load', t.step_func_done(() => {
    124    assert_true(client.status == 200 && client.responseXML != null);
    125    assert_dsd(client.responseXML.body,false);
    126    t.done();
    127  }));
    128  client.open("GET", `data:text/html,${content}`);
    129  client.responseType = 'document';
    130  client.send();
    131 }, 'XMLHttpRequest - not supported');
    132 
    133 test(() => {
    134  const div = document.createElement('div');
    135  div.insertAdjacentHTML('afterbegin',content);
    136  assert_dsd(div,false);
    137 }, 'insertAdjacentHTML on element - not supported');
    138 
    139 test(() => {
    140  const id = 'doc-write-1';
    141  document.write(`<div id=${id} style="display:none">${content}</div>`);
    142  assert_dsd(document.getElementById(id),true);
    143 }, 'document.write allowed from synchronous script loaded from main document');
    144 
    145 test(() => {
    146  const id = 'doc-write-2';
    147  const doc = document.implementation.createHTMLDocument('');
    148  doc.write(`<div id=${id}>${content}</div>`);
    149  assert_dsd(doc.getElementById(id),false);
    150 }, 'document.write disallowed on fresh document');
    151 
    152 
    153 async_test((t) => {
    154  const iframe = document.createElement('iframe');
    155  iframe.style.display = "none";
    156  iframe.sandbox = "allow-same-origin";
    157  document.body.appendChild(iframe);
    158  iframe.addEventListener('load', t.step_func_done(() => {
    159    assert_dsd(iframe.contentDocument.body,true);
    160    t.done();
    161  }));
    162  iframe.srcdoc = content;
    163 }, 'iframe');
    164 
    165 async_test((t) => {
    166  const iframe = document.createElement('iframe');
    167  iframe.style.display = "none";
    168  document.body.appendChild(iframe);
    169  iframe.addEventListener('load', t.step_func_done(() => {
    170    assert_dsd(iframe.contentDocument.body,true);
    171    t.done();
    172  }));
    173  iframe.srcdoc = content;
    174 }, 'iframe, no sandbox');
    175 
    176 function getHandler(t, name, shouldHaveShadow) {
    177  return (e) => {
    178    t.step(() => {
    179      if (e.data.name == name) {
    180        assert_false(e.data.error,e.data.msg);
    181        assert_true(e.data.hasShadow == shouldHaveShadow);
    182        t.done();
    183      }
    184    });
    185  };
    186 }
    187 async_test((t) => {
    188  window.addEventListener('message', getHandler(t, 'iframe-sandbox', true));
    189 }, 'sandboxed iframe allows declarative Shadow DOM');
    190 
    191 async_test((t) => {
    192  window.addEventListener('message', getHandler(t,'iframe-no-sandbox', true));
    193 }, 'iframe with no sandbox allows declarative Shadow DOM');
    194 
    195 </script>
    196 
    197 <iframe name="iframe-sandbox" sandbox="allow-scripts" src="support/declarative-child-frame.html" ></iframe>
    198 <iframe name="iframe-no-sandbox" src="support/declarative-child-frame.html"></iframe>