diff --git a/moli-renderer-v8/src/script_vm/tests/dom_xhr/dom.rs b/moli-renderer-v8/src/script_vm/tests/dom_xhr/dom.rs index 62455cc74..44133f3b6 100644 --- a/moli-renderer-v8/src/script_vm/tests/dom_xhr/dom.rs +++ b/moli-renderer-v8/src/script_vm/tests/dom_xhr/dom.rs @@ -13,9819 +13,15 @@ where .expect("large-stack DOM test thread should finish"); } -#[test] -fn child_document_create_text_and_comment_nodes_work() { - let mut vm = new_storage_test_vm("https://child-window-detached-text.test/"); - - let result = vm - .eval( - r#" -(() => { - const frame = document.createElement('iframe'); - frame.srcdoc = '
'; - (document.body || document.documentElement || document).appendChild(frame); - const doc = frame.contentDocument; - const text = doc.createTextNode('hello'); - const comment = doc.createComment('note'); - doc.body.appendChild(text); - doc.body.appendChild(comment); - return [ - typeof doc.createTextNode, - text.nodeType, - text.nodeName, - text.data, - text.parentNode === doc.body, - typeof doc.createComment, - comment.nodeType, - comment.nodeName, - comment.data, - doc.body.childNodes.length - ].join('|'); -})() -"#, - ) - .expect("detached child document text/comment nodes should work"); - - assert_eq!( - result, - "function|3|#text|hello|true|function|8|#comment|note|2" - ); -} -#[test] -fn detached_character_data_accessors_parse_webidl_arguments() { - let mut vm = new_storage_test_vm("https://detached-character-data-webidl.test/"); - - let result = vm - .eval( - r#" -(() => { - const doc = document.implementation.createHTMLDocument(""); - const text = doc.createTextNode("seed"); - const comment = doc.createComment("note"); - const probe = callback => { - try { - callback(); - return "no-throw"; - } catch (error) { - return "throw:" + error.name; - } - }; - text.data = { toString() { return "updated"; } }; - const dataSymbol = probe(() => { text.data = Symbol("data"); }); - text.nodeValue = { toString() { return "node-value"; } }; - const nodeSymbol = probe(() => { comment.nodeValue = Symbol("nodeValue"); }); - comment.data = null; - return [ - text.data, - text.nodeValue, - dataSymbol, - comment.data, - nodeSymbol - ].join("|"); -})() -"#, - ) - .expect("detached character data WebIDL accessors should evaluate"); - - assert_eq!( - result, - "node-value|node-value|throw:TypeError||throw:TypeError" - ); -} -#[test] -fn live_node_replace_child_rejects_non_child_with_not_found_error() { - let mut vm = new_storage_test_vm("https://live-node-replace-not-found.test/"); - - let result = vm - .eval( - r#" -(() => { - const parent = document.createElement('div'); - const oldChild = document.createElement('span'); - const newChild = document.createElement('b'); - (document.body || document.documentElement || document).appendChild(parent); - try { - parent.replaceChild(newChild, oldChild); - return 'missing'; - } catch (error) { - return [ - error.name, - error.code, - parent.childNodes.length, - newChild.parentNode === null, - oldChild.parentNode === null - ].join('|'); - } -})() -"#, - ) - .expect("live replaceChild should reject a non-child oldChild"); - - assert_eq!(result, "NotFoundError|8|0|true|true"); -} -#[test] -fn detached_document_fragment_inserts_children_and_empties_fragment() { - let mut vm = new_storage_test_vm("https://detached-document-fragment.test/"); - - let result = vm - .eval( - r#" -(() => { - const doc = new DOMParser().parseFromString( - '', - 'text/html' - ); - const fragment = doc.createDocumentFragment(); - const first = doc.createElement('a'); - first.id = 'first'; - const text = doc.createTextNode('text'); - const second = doc.createElement('b'); - second.id = 'second'; - fragment.appendChild(first); - fragment.appendChild(text); - fragment.appendChild(second); - const beforeInsertConnected = [ - fragment.isConnected, - first.isConnected, - text.isConnected, - second.isConnected - ].join(','); - const returned = doc.body.insertBefore(fragment, doc.getElementById('end')); - return [ - typeof doc.createDocumentFragment, - Object.prototype.toString.call(fragment), - fragment instanceof DocumentFragment, - fragment.nodeType, - fragment.nodeName, - beforeInsertConnected, - returned === fragment, - fragment.childNodes.length, - fragment.children.length, - fragment.firstChild === null, - doc.body.childNodes.length, - doc.body.children.length, - doc.body.firstChild === first, - first.nextSibling === text, - text.nextSibling === second, - second.nextSibling.id, - second.previousSibling === text, - first.parentNode === doc.body, - second.parentNode === doc.body, - first.isConnected, - text.isConnected, - second.isConnected - ].join('|'); -})() -"#, - ) - .expect("detached DocumentFragment should insert children and empty itself"); - - assert_eq!( - result, - "function|[object DocumentFragment]|true|11|#document-fragment|false,false,false,false|true|0|0|true|4|3|true|true|true|end|true|true|true|true|true|true" - ); -} -#[test] -fn document_fragment_constructor_uses_live_document_fragment_semantics() { - let mut vm = new_storage_test_vm("https://document-fragment-constructor.test/"); - - let result = vm - .eval( - r#" -(() => { - if (!document.documentElement) { - document.appendChild(document.createElement('html')); - } - if (!document.body) { - document.documentElement.appendChild(document.createElement('body')); - } - const constructed = new DocumentFragment(); - const factory = document.createDocumentFragment(); - - function run(label, fragment) { - const node = document.createElement('div'); - node.id = label; - fragment.appendChild(node); - const afterFragment = node.parentNode && node.parentNode.nodeName; - document.body.appendChild(fragment); - const afterBody = node.parentNode && node.parentNode.nodeName; - const sameById = document.getElementById(label) === node; - const contains = document.body.contains(node); - const removed = node.parentNode.removeChild(node); - return [ - afterFragment, - afterBody, - sameById, - contains, - removed === node, - node.parentNode === null, - fragment.childNodes.length - ].join(','); - } - - return [ - Object.prototype.toString.call(constructed), - constructed instanceof DocumentFragment, - run('ctor-fragment-child', constructed), - run('factory-fragment-child', factory) - ].join('|'); -})() -"#, - ) - .expect("DocumentFragment constructor should match document factory semantics"); - - assert_eq!( - result, - "[object DocumentFragment]|true|#document-fragment,BODY,true,true,true,true,0|#document-fragment,BODY,true,true,true,true,0" - ); -} -#[test] -fn document_fragment_constructor_falls_back_cleanly_when_live_getter_throws() { - let mut vm = new_storage_test_vm("https://document-fragment-constructor-throw.test/"); - - let result = vm - .eval( - r#" -(() => { - Object.defineProperty(document, 'createDocumentFragment', { - configurable: true, - get() { - throw new Error('getter boom'); - } - }); - const fragment = new DocumentFragment(); - const child = document.createElement('span'); - child.id = 'fallback-fragment-child'; - fragment.appendChild(child); - return [ - Object.prototype.toString.call(fragment), - fragment instanceof DocumentFragment, - fragment.nodeType, - fragment.nodeName, - fragment.ownerDocument === document, - fragment.firstChild === child, - fragment.childNodes.length - ].join('|'); -})() -"#, - ) - .expect("DocumentFragment constructor fallback should clear thrown getter state"); - - assert_eq!( - result, - "[object DocumentFragment]|true|11|#document-fragment|true|true|1" - ); -} -#[test] -fn detached_doctype_append_preserves_parent_and_owner_document() { - let mut vm = new_storage_test_vm("https://detached-doctype-parent.test/"); - - let result = vm - .eval( - r#" -(() => { - const doc = document.implementation.createDocument(null, "", null); - const doctype = doc.implementation.createDocumentType("html", "", ""); - const appended = doc.appendChild(doctype); - const before = [ - appended === doctype, - doctype.parentNode === doc, - doctype.ownerDocument === doc, - String(doctype.parentNode), - String(doctype.ownerDocument), - doc.childNodes.length, - doc.childNodes[0] === doctype, - String(doc.childNodes[0]), - doc.firstChild === doctype, - String(doc.firstChild) - ].join(","); - doctype.remove(); - const after = [ - doctype.parentNode === null, - doctype.ownerDocument === doc, - String(doctype.parentNode), - String(doctype.ownerDocument) - ].join(","); - return before + "|" + after; -})() -"#, - ) - .expect("detached doctype parent/owner probe should evaluate"); - - assert_eq!( - result, - "true,true,true,[object XMLDocument],[object XMLDocument],1,true,[object DocumentType],true,[object DocumentType]|true,true,null,[object XMLDocument]" - ); -} -#[test] -fn detached_node_remove_child_and_remove_refresh_parent_surface() { - let mut vm = new_storage_test_vm("https://detached-node-remove-child.test/"); - - let result = vm - .eval( - r#" -(() => { - const doc = new DOMParser().parseFromString( - '', - 'text/html' - ); - const a = doc.getElementById('a'); - const b = doc.getElementById('b'); - const c = doc.getElementById('c'); - const nested = doc.getElementById('nested'); - const removed = doc.body.removeChild(b); - c.remove(); - return [ - typeof doc.body.removeChild, - removed === b, - b.parentNode === null, - b.previousSibling === null, - b.nextSibling === null, - b.isConnected, - c.parentNode === null, - c.isConnected, - nested.isConnected, - doc.body.childNodes.length, - doc.body.children.length, - doc.body.firstChild === a, - doc.body.lastChild === a, - a.previousSibling === null, - a.nextSibling === null, - doc.body.children.item(0) === a, - doc.body.children.item(1) === null - ].join('|'); -})() -"#, - ) - .expect("detached removeChild/remove should refresh parent surface"); - - assert_eq!( - result, - "function|true|true|true|true|false|true|false|false|1|1|true|true|true|true|true|true" - ); -} -#[test] -fn element_insert_adjacent_methods_parse_webidl_arguments() { - let mut vm = new_storage_test_vm("https://insert-adjacent-webidl.test/"); - - let result = vm - .eval( - r#" -(() => { - const probe = callback => { - try { - const value = callback(); - return value === undefined ? 'undefined' : String(value); - } catch (error) { - return `throw:${error && error.name}`; - } - }; - const root = document.createElement('div'); - const span = document.createElement('span'); - span.textContent = 'element'; - const returned = root.insertAdjacentElement({ toString() { return 'beforeend'; } }, span); - root.insertAdjacentText({ toString() { return 'beforeend'; } }, { - toString() { - return 'text'; - } - }); - root.insertAdjacentText('beforeend', undefined); - root.insertAdjacentHTML('beforeend', { - toString() { - return 'bold'; - } - }); - return [ - returned === span, - root.textContent, - root.querySelector('#inserted').textContent, - probe(() => root.insertAdjacentText()), - probe(() => root.insertAdjacentText(Symbol(), 'x')), - probe(() => root.insertAdjacentText({ - toString() { - throw new RangeError('position'); - } - }, 'x')), - probe(() => root.insertAdjacentText('beforeend', Symbol())), - probe(() => root.insertAdjacentText('sideways', 'x')), - probe(() => root.insertAdjacentHTML('beforeend')), - probe(() => root.insertAdjacentHTML('beforeend', Symbol())), - probe(() => root.insertAdjacentElement('beforeend')), - probe(() => root.insertAdjacentElement(Symbol(), span)) - ].join('|'); -})() -"#, - ) - .expect("insertAdjacent methods should parse WebIDL arguments"); - - assert_eq!( - result, - "true|elementtextundefinedbold|bold|throw:TypeError|throw:TypeError|throw:RangeError|throw:TypeError|throw:SyntaxError|throw:TypeError|throw:TypeError|throw:TypeError|throw:TypeError" - ); -} -#[test] -fn document_fragment_and_shadow_root_get_element_by_id_match_browser_lookup_boundaries() { - let mut vm = new_storage_test_vm("https://fragment-shadow-get-by-id.test/"); - - let result = vm - .eval( - r#" -(() => { - if (!document.documentElement) { - document.appendChild(document.createElement('html')); - } - if (!document.body) { - document.documentElement.appendChild(document.createElement('body')); - } - const host = document.createElement('div'); - document.body.appendChild(host); - - const fragment = document.createDocumentFragment(); - const outer = document.createElement('section'); - const inner = document.createElement('span'); - outer.id = 'outer'; - inner.id = 'inside-fragment'; - outer.appendChild(inner); - fragment.appendChild(outer); - - const shadow = host.attachShadow({ mode: 'open' }); - shadow.innerHTML = '