From 0e803ffaf3ef8f1bbd93d023acb0e4f283dd9d71 Mon Sep 17 00:00:00 2001 From: "Achim D. Brucker" Date: Sat, 19 Dec 2020 11:09:06 +0000 Subject: [PATCH] Initial import from AFP. --- DOM_Components/Core_DOM_Components.thy | 2154 +++++++++++++++++ DOM_Components/ROOT | 14 + DOM_Components/Shadow_DOM_Components.thy | 1564 ++++++++++++ DOM_Components/counterexample/fancy-tabs.html | 40 + DOM_Components/counterexample/fancy_tabs.thy | 96 + DOM_Components/document/fancytabs-normal.jpg | Bin 0 -> 34081 bytes DOM_Components/document/root.bib | 747 ++++++ DOM_Components/document/root.tex | 238 ++ 8 files changed, 4853 insertions(+) create mode 100644 DOM_Components/Core_DOM_Components.thy create mode 100644 DOM_Components/ROOT create mode 100644 DOM_Components/Shadow_DOM_Components.thy create mode 100644 DOM_Components/counterexample/fancy-tabs.html create mode 100644 DOM_Components/counterexample/fancy_tabs.thy create mode 100644 DOM_Components/document/fancytabs-normal.jpg create mode 100644 DOM_Components/document/root.bib create mode 100644 DOM_Components/document/root.tex diff --git a/DOM_Components/Core_DOM_Components.thy b/DOM_Components/Core_DOM_Components.thy new file mode 100644 index 0000000..7ad4f05 --- /dev/null +++ b/DOM_Components/Core_DOM_Components.thy @@ -0,0 +1,2154 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + + +section \DOM Components\ + +theory Core_DOM_Components + imports Core_DOM.Core_DOM +begin + + +locale l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs = + l_get_root_node_defs get_root_node get_root_node_locs + + l_to_tree_order_defs to_tree_order + for get_root_node :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_locs :: "((_) heap \ (_) heap \ bool) set" + and to_tree_order :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" +begin + +definition a_get_component :: "(_) object_ptr \ (_, (_) object_ptr list) dom_prog" + where + "a_get_component ptr = do { + root \ get_root_node ptr; + to_tree_order root + }" + +definition a_is_strongly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + where + "a_is_strongly_dom_component_safe S\<^sub>a\<^sub>r\<^sub>g S\<^sub>r\<^sub>e\<^sub>s\<^sub>u\<^sub>l\<^sub>t h h' = ( + let removed_pointers = fset (object_ptr_kinds h) - fset (object_ptr_kinds h') in + let added_pointers = fset (object_ptr_kinds h') - fset (object_ptr_kinds h) in + let arg_components = + (\ptr \ (\ptr \ S\<^sub>a\<^sub>r\<^sub>g. set |h \ a_get_component ptr|\<^sub>r) \ fset (object_ptr_kinds h). + set |h \ a_get_component ptr|\<^sub>r) in + let arg_components' = + (\ptr \ (\ptr \ S\<^sub>a\<^sub>r\<^sub>g. set |h \ a_get_component ptr|\<^sub>r) \ fset (object_ptr_kinds h'). + set |h' \ a_get_component ptr|\<^sub>r) in + removed_pointers \ arg_components \ + added_pointers \ arg_components' \ + S\<^sub>r\<^sub>e\<^sub>s\<^sub>u\<^sub>l\<^sub>t \ arg_components' \ + (\outside_ptr \ fset (object_ptr_kinds h) \ fset (object_ptr_kinds h') - + (\ptr \ S\<^sub>a\<^sub>r\<^sub>g. set |h \ a_get_component ptr|\<^sub>r). preserved (get_M outside_ptr id) h h'))" + +definition a_is_weakly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + where + "a_is_weakly_dom_component_safe S\<^sub>a\<^sub>r\<^sub>g S\<^sub>r\<^sub>e\<^sub>s\<^sub>u\<^sub>l\<^sub>t h h' = ( + let removed_pointers = fset (object_ptr_kinds h) - fset (object_ptr_kinds h') in + let added_pointers = fset (object_ptr_kinds h') - fset (object_ptr_kinds h) in + let arg_components = + (\ptr \ (\ptr \ S\<^sub>a\<^sub>r\<^sub>g. set |h \ a_get_component ptr|\<^sub>r) \ fset (object_ptr_kinds h). + set |h \ a_get_component ptr|\<^sub>r) in + let arg_components' = + (\ptr \ (\ptr \ S\<^sub>a\<^sub>r\<^sub>g. set |h \ a_get_component ptr|\<^sub>r) \ fset (object_ptr_kinds h'). + set |h' \ a_get_component ptr|\<^sub>r) in + removed_pointers \ arg_components \ + S\<^sub>r\<^sub>e\<^sub>s\<^sub>u\<^sub>l\<^sub>t \ arg_components' \ added_pointers \ + (\outside_ptr \ fset (object_ptr_kinds h) \ fset (object_ptr_kinds h') - + (\ptr \ S\<^sub>a\<^sub>r\<^sub>g. set |h \ a_get_component ptr|\<^sub>r). preserved (get_M outside_ptr id) h h'))" + +lemma "a_is_strongly_dom_component_safe S\<^sub>a\<^sub>r\<^sub>g S\<^sub>r\<^sub>e\<^sub>s\<^sub>u\<^sub>l\<^sub>t h h' \ a_is_weakly_dom_component_safe S\<^sub>a\<^sub>r\<^sub>g S\<^sub>r\<^sub>e\<^sub>s\<^sub>u\<^sub>l\<^sub>t h h'" + by(auto simp add: a_is_strongly_dom_component_safe_def a_is_weakly_dom_component_safe_def Let_def) + +definition is_document_component :: "(_) object_ptr list \ bool" + where + "is_document_component c = is_document_ptr_kind (hd c)" + +definition is_disconnected_component :: "(_) object_ptr list \ bool" + where + "is_disconnected_component c = is_node_ptr_kind (hd c)" +end + +global_interpretation l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_root_node get_root_node_locs to_tree_order + defines get_component = a_get_component + and is_strongly_dom_component_safe = a_is_strongly_dom_component_safe + and is_weakly_dom_component_safe = a_is_weakly_dom_component_safe + . + + +locale l_get_component_defs = + fixes get_component :: "(_) object_ptr \ (_, (_) object_ptr list) dom_prog" + fixes is_strongly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + fixes is_weakly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + +locale l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_to_tree_order_wf + + l_get_component_defs + + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs + + l_get_ancestors + + l_get_ancestors_wf + + l_get_root_node + + l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent + + l_get_parent_wf + + l_get_element_by + + l_to_tree_order_wf_get_root_node_wf + + (* l_to_tree_order_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ _ _ get_child_nodes + + l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ _ get_child_nodes+ + l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ _ "l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.a_to_tree_order get_child_nodes" + for get_child_nodes :: "(_::linorder) object_ptr \ (_, (_) node_ptr list) dom_prog" *) + assumes get_component_impl: "get_component = a_get_component" + assumes is_strongly_dom_component_safe_impl: + "is_strongly_dom_component_safe = a_is_strongly_dom_component_safe" + assumes is_weakly_dom_component_safe_impl: + "is_weakly_dom_component_safe = a_is_weakly_dom_component_safe" +begin +lemmas get_component_def = a_get_component_def[folded get_component_impl] +lemmas is_strongly_dom_component_safe_def = + a_is_strongly_dom_component_safe_def[folded is_strongly_dom_component_safe_impl] +lemmas is_weakly_dom_component_safe_def = + a_is_weakly_dom_component_safe_def[folded is_weakly_dom_component_safe_impl] + +lemma get_dom_component_ptr_in_heap: + assumes "h \ ok (get_component ptr)" + shows "ptr |\| object_ptr_kinds h" + using assms get_root_node_ptr_in_heap + by(auto simp add: get_component_def) + +lemma get_component_ok: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "ptr |\| object_ptr_kinds h" + shows "h \ ok (get_component ptr)" + using assms + apply(auto simp add: get_component_def a_get_root_node_def intro!: bind_is_OK_pure_I)[1] + using get_root_node_ok to_tree_order_ok get_root_node_ptr_in_heap + apply blast + by (simp add: local.get_root_node_root_in_heap local.to_tree_order_ok) + +lemma get_dom_component_ptr: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + shows "ptr \ set c" +proof(insert assms(1) assms(4), induct ptr rule: heap_wellformed_induct_rev ) + case (step child) + then show ?case + proof (cases "is_node_ptr_kind child") + case True + obtain node_ptr where + node_ptr: "cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr = child" + using \is_node_ptr_kind child\ node_ptr_casts_commute3 by blast + have "child |\| object_ptr_kinds h" + using \h \ get_component child \\<^sub>r c\ get_dom_component_ptr_in_heap by fast + with node_ptr have "node_ptr |\| node_ptr_kinds h" + by auto + then obtain parent_opt where + parent: "h \ get_parent node_ptr \\<^sub>r parent_opt" + using get_parent_ok \type_wf h\ \known_ptrs h\ + by fast + then show ?thesis + proof (induct parent_opt) + case None + then have "h \ get_root_node (cast node_ptr) \\<^sub>r cast node_ptr" + by (simp add: local.get_root_node_no_parent) + then show ?case + using \type_wf h\ \known_ptrs h\ node_ptr step(2) + apply(auto simp add: get_component_def a_get_root_node_def elim!: bind_returns_result_E2)[1] + using to_tree_order_ptr_in_result returns_result_eq by fastforce + next + case (Some parent_ptr) + then have "h \ get_component parent_ptr \\<^sub>r c" + using step(2) node_ptr \type_wf h\ \known_ptrs h\ \heap_is_wellformed h\ + get_root_node_parent_same + by(auto simp add: get_component_def elim!: bind_returns_result_E2 intro!: bind_pure_returns_result_I) + then have "parent_ptr \ set c" + using step node_ptr Some by blast + then show ?case + using \type_wf h\ \known_ptrs h\ \heap_is_wellformed h\ step(2) node_ptr Some + apply(auto simp add: get_component_def elim!: bind_returns_result_E2)[1] + using to_tree_order_parent by blast + qed + next + case False + then show ?thesis + using \type_wf h\ \known_ptrs h\ step(2) + apply(auto simp add: get_component_def elim!: bind_returns_result_E2)[1] + by (metis is_OK_returns_result_I local.get_root_node_not_node_same + local.get_root_node_ptr_in_heap local.to_tree_order_ptr_in_result returns_result_eq) + qed +qed + +lemma get_component_parent_inside: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "cast node_ptr \ set c" + assumes "h \ get_parent node_ptr \\<^sub>r Some parent" + shows "parent \ set c" +proof - + have "parent |\| object_ptr_kinds h" + using assms(6) get_parent_parent_in_heap by blast + + obtain root_ptr where root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" and + c: "h \ to_tree_order root_ptr \\<^sub>r c" + using assms(4) + by (metis (no_types, hide_lams) bind_returns_result_E2 get_component_def get_root_node_pure) + then have "h \ get_root_node (cast node_ptr) \\<^sub>r root_ptr" + using assms(1) assms(2) assms(3) assms(5) to_tree_order_same_root by blast + then have "h \ get_root_node parent \\<^sub>r root_ptr" + using assms(6) get_root_node_parent_same by blast + then have "h \ get_component parent \\<^sub>r c" + using c get_component_def by auto + then show ?thesis + using assms(1) assms(2) assms(3) get_dom_component_ptr by blast +qed + +lemma get_component_subset: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "ptr' \ set c" + shows "h \ get_component ptr' \\<^sub>r c" +proof(insert assms(1) assms(5), induct ptr' rule: heap_wellformed_induct_rev ) + case (step child) + then show ?case + proof (cases "is_node_ptr_kind child") + case True + obtain node_ptr where + node_ptr: "cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr = child" + using \is_node_ptr_kind child\ node_ptr_casts_commute3 by blast + have "child |\| object_ptr_kinds h" + using to_tree_order_ptrs_in_heap assms(1) assms(2) assms(3) assms(4) step(2) + unfolding get_component_def + by (meson bind_returns_result_E2 get_root_node_pure) + with node_ptr have "node_ptr |\| node_ptr_kinds h" + by auto + then obtain parent_opt where + parent: "h \ get_parent node_ptr \\<^sub>r parent_opt" + using get_parent_ok \type_wf h\ \known_ptrs h\ + by fast + then show ?thesis + proof (induct parent_opt) + case None + then have "h \ get_root_node child \\<^sub>r child" + using assms(1) get_root_node_no_parent node_ptr by blast + then show ?case + using \type_wf h\ \known_ptrs h\ node_ptr step(2) assms(4) assms(1) + by (metis (no_types) bind_pure_returns_result_I2 bind_returns_result_E2 get_component_def + get_root_node_pure is_OK_returns_result_I returns_result_eq to_tree_order_same_root) + next + case (Some parent_ptr) + then have "h \ get_component parent_ptr \\<^sub>r c" + using step get_component_parent_inside assms node_ptr by blast + then show ?case + using Some node_ptr + apply(auto simp add: get_component_def elim!: bind_returns_result_E2 + del: bind_pure_returns_result_I intro!: bind_pure_returns_result_I)[1] + using get_root_node_parent_same by blast + qed + next + case False + then have "child |\| object_ptr_kinds h" + using assms(1) assms(4) step(2) + by (metis (no_types, lifting) assms(2) assms(3) bind_returns_result_E2 get_root_node_pure + get_component_def to_tree_order_ptrs_in_heap) + then have "h \ get_root_node child \\<^sub>r child" + using assms(1) False get_root_node_not_node_same by blast + then show ?thesis + using assms(1) assms(2) assms(3) assms(4) step.prems + by (metis (no_types) False \child |\| object_ptr_kinds h\ bind_pure_returns_result_I2 + bind_returns_result_E2 get_component_def get_root_node_ok get_root_node_pure returns_result_eq + to_tree_order_node_ptrs) + qed +qed + +lemma get_component_to_tree_order_subset: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ to_tree_order ptr \\<^sub>r nodes" + assumes "h \ get_component ptr \\<^sub>r c" + shows "set nodes \ set c" + using assms + apply(auto simp add: get_component_def elim!: bind_returns_result_E2)[1] + by (meson to_tree_order_subset assms(5) contra_subsetD get_dom_component_ptr) + +lemma get_component_to_tree_order: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ to_tree_order ptr' \\<^sub>r to" + assumes "ptr \ set to" + shows "h \ get_component ptr' \\<^sub>r c" + by (metis (no_types, hide_lams) assms(1) assms(2) assms(3) assms(4) assms(5) assms(6) + get_component_ok get_component_subset get_component_to_tree_order_subset is_OK_returns_result_E + local.to_tree_order_ptr_in_result local.to_tree_order_ptrs_in_heap select_result_I2 subsetCE) + +lemma get_component_root_node_same: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_root_node ptr \\<^sub>r root_ptr" + assumes "x \ set c" + shows "h \ get_root_node x \\<^sub>r root_ptr" +proof(insert assms(1) assms(6), induct x rule: heap_wellformed_induct_rev ) + case (step child) + then show ?case + proof (cases "is_node_ptr_kind child") + case True + obtain node_ptr where + node_ptr: "cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r node_ptr = child" + using \is_node_ptr_kind child\ node_ptr_casts_commute3 by blast + have "child |\| object_ptr_kinds h" + using to_tree_order_ptrs_in_heap assms(1) assms(2) assms(3) assms(4) step(2) + unfolding get_component_def + by (meson bind_returns_result_E2 get_root_node_pure) + with node_ptr have "node_ptr |\| node_ptr_kinds h" + by auto + then obtain parent_opt where + parent: "h \ get_parent node_ptr \\<^sub>r parent_opt" + using get_parent_ok \type_wf h\ \known_ptrs h\ + by fast + then show ?thesis + proof (induct parent_opt) + case None + then have "h \ get_root_node child \\<^sub>r child" + using assms(1) get_root_node_no_parent node_ptr by blast + then show ?case + using \type_wf h\ \known_ptrs h\ node_ptr step(2) assms(4) assms(1) assms(5) + by (metis (no_types) \child |\| object_ptr_kinds h\ bind_pure_returns_result_I + get_component_def get_dom_component_ptr get_component_subset get_root_node_pure is_OK_returns_result_E + returns_result_eq to_tree_order_ok to_tree_order_same_root) + next + case (Some parent_ptr) + then have "h \ get_component parent_ptr \\<^sub>r c" + using step get_component_parent_inside assms node_ptr + by (meson get_component_subset) + then show ?case + using Some node_ptr + apply(auto simp add: get_component_def elim!: bind_returns_result_E2)[1] + using get_root_node_parent_same + using \h \ get_component parent_ptr \\<^sub>r c\ assms(1) assms(2) assms(3) get_dom_component_ptr + step.hyps + by blast + qed + next + case False + then have "child |\| object_ptr_kinds h" + using assms(1) assms(4) step(2) + by (metis (no_types, lifting) assms(2) assms(3) bind_returns_result_E2 get_root_node_pure + get_component_def to_tree_order_ptrs_in_heap) + then have "h \ get_root_node child \\<^sub>r child" + using assms(1) False get_root_node_not_node_same by auto + then show ?thesis + using assms(1) assms(2) assms(3) assms(4) step.prems assms(5) + by (metis (no_types, hide_lams) bind_returns_result_E2 get_component_def get_root_node_pure + returns_result_eq to_tree_order_same_root) + qed +qed + + +lemma get_dom_component_no_overlap: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_component ptr' \\<^sub>r c'" + shows "set c \ set c' = {} \ c = c'" +proof (rule ccontr, auto) + fix x + assume 1: "c \ c'" and 2: "x \ set c" and 3: "x \ set c'" + obtain root_ptr where root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + using assms(4) unfolding get_component_def + by (meson bind_is_OK_E is_OK_returns_result_I) + moreover obtain root_ptr' where root_ptr': "h \ get_root_node ptr' \\<^sub>r root_ptr'" + using assms(5) unfolding get_component_def + by (meson bind_is_OK_E is_OK_returns_result_I) + ultimately have "root_ptr \ root_ptr'" + using 1 assms + unfolding get_component_def + by (meson bind_returns_result_E3 get_root_node_pure returns_result_eq) + + moreover have "h \ get_root_node x \\<^sub>r root_ptr" + using 2 root_ptr get_component_root_node_same assms by blast + moreover have "h \ get_root_node x \\<^sub>r root_ptr'" + using 3 root_ptr' get_component_root_node_same assms by blast + ultimately show False + using select_result_I2 by force +qed + +lemma get_component_separates_tree_order: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ to_tree_order ptr \\<^sub>r to" + assumes "h \ get_component ptr' \\<^sub>r c'" + assumes "ptr' \ set c" + shows "set to \ set c' = {}" +proof - + have "c \ c'" + using assms get_dom_component_ptr by blast + then have "set c \ set c' = {}" + using assms get_dom_component_no_overlap by blast + moreover have "set to \ set c" + using assms get_component_to_tree_order_subset by blast + ultimately show ?thesis + by blast +qed + +lemma get_component_separates_tree_order_general: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ to_tree_order ptr'' \\<^sub>r to''" + assumes "ptr'' \ set c" + assumes "h \ get_component ptr' \\<^sub>r c'" + assumes "ptr' \ set c" + shows "set to'' \ set c' = {}" +proof - + obtain root_ptr where root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + using assms(4) + by (metis bind_is_OK_E get_component_def is_OK_returns_result_I) + then have c: "h \ to_tree_order root_ptr \\<^sub>r c" + using assms(4) unfolding get_component_def + by (simp add: bind_returns_result_E3) + with root_ptr show ?thesis + using assms get_component_separates_tree_order get_component_subset + by meson +qed +end + +interpretation i_get_component?: l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name + by(auto simp add: l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def get_component_def + is_strongly_dom_component_safe_def is_weakly_dom_component_safe_def instances) +declare l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \get\_child\_nodes\ + +locale l_get_component_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma get_dom_component_get_child_nodes: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_child_nodes ptr' \\<^sub>r children" + assumes "child \ set children" + shows "cast child \ set c \ ptr' \ set c" +proof + assume 1: "cast child \ set c" + obtain root_ptr where + root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + by (metis assms(4) bind_is_OK_E get_component_def is_OK_returns_result_I) + have "h \ get_root_node (cast child) \\<^sub>r root_ptr" + using "1" assms(1) assms(2) assms(3) assms(4) get_component_root_node_same root_ptr + by blast + then have "h \ get_root_node ptr' \\<^sub>r root_ptr" + using assms(1) assms(2) assms(3) assms(5) assms(6) local.child_parent_dual + local.get_root_node_parent_same + by blast + then have "h \ get_component ptr' \\<^sub>r c" + using "1" assms(1) assms(2) assms(3) assms(4) assms(5) assms(6) local.child_parent_dual + local.get_component_parent_inside local.get_component_subset + by blast + then show "ptr' \ set c" + using assms(1) assms(2) assms(3) get_dom_component_ptr + by blast +next + assume 1: "ptr' \ set c" + obtain root_ptr where + root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + by (metis assms(4) bind_is_OK_E get_component_def is_OK_returns_result_I) + have "h \ get_root_node ptr' \\<^sub>r root_ptr" + using "1" assms(1) assms(2) assms(3) assms(4) get_component_root_node_same root_ptr + by blast + then have "h \ get_root_node (cast child) \\<^sub>r root_ptr" + using assms(1) assms(2) assms(3) assms(5) assms(6) local.child_parent_dual local.get_root_node_parent_same + by blast + then have "h \ get_component ptr' \\<^sub>r c" + using "1" assms(1) assms(2) assms(3) assms(4) assms(5) assms(6) local.child_parent_dual + local.get_component_parent_inside local.get_component_subset + by blast + then show "cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r child \ set c" + by (smt \h \ get_root_node (cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r child) \\<^sub>r root_ptr\ assms(1) assms(2) assms(3) + assms(5) assms(6) disjoint_iff_not_equal is_OK_returns_result_E is_OK_returns_result_I + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_dom_component_no_overlap local.child_parent_dual local.get_component_ok + local.get_component_parent_inside local.get_dom_component_ptr local.get_root_node_ptr_in_heap + local.l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms) +qed + + +lemma get_child_nodes_get_component: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_child_nodes ptr \\<^sub>r children" + shows "cast ` set children \ set c" + using assms get_dom_component_get_child_nodes + using local.get_dom_component_ptr by auto + + +lemma get_child_nodes_strongly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_child_nodes ptr \\<^sub>r children" + assumes "h \ get_child_nodes ptr \\<^sub>h h'" + shows "is_strongly_dom_component_safe {ptr} (cast ` set children) h h'" +proof - + have "h = h'" + using assms(5) + by (meson local.get_child_nodes_pure pure_returns_heap_eq) + then show ?thesis + using assms + apply(auto simp add: is_strongly_dom_component_safe_def Let_def preserved_def)[1] + by (smt IntI finite_set_in get_dom_component_get_child_nodes is_OK_returns_result_E + is_OK_returns_result_I local.get_child_nodes_ptr_in_heap local.get_component_impl + local.get_component_ok local.get_dom_component_ptr select_result_I2) +qed +end + +interpretation i_get_component_get_child_nodes?: l_get_component_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name first_in_tree_order get_attribute get_attribute_locs + by(auto simp add: l_get_component_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \get\_parent\ + +locale l_get_component_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma get_parent_is_strongly_dom_component_safe_step: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_parent ptr' \\<^sub>r Some parent" + shows "parent \ set c \ cast ptr' \ set c" + by (meson assms(1) assms(2) assms(3) assms(4) assms(5) is_OK_returns_result_E + l_to_tree_order_wf.to_tree_order_parent local.get_component_parent_inside local.get_component_subset + local.get_component_to_tree_order_subset local.get_parent_parent_in_heap local.l_to_tree_order_wf_axioms + local.to_tree_order_ok local.to_tree_order_ptr_in_result subsetCE) + + +lemma get_parent_is_strongly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_parent node_ptr \\<^sub>r Some parent" + assumes "h \ get_parent node_ptr \\<^sub>h h'" + shows "is_strongly_dom_component_safe {cast node_ptr} {parent} h h'" +proof - + have "h = h'" + using assms(5) + by (meson local.get_parent_pure pure_returns_heap_eq) + then show ?thesis + using assms + apply(auto simp add: is_strongly_dom_component_safe_def Let_def preserved_def)[1] + using get_dom_component_get_child_nodes local.get_component_impl local.get_dom_component_ptr + by (metis (no_types, hide_lams) Int_iff finite_set_in get_parent_is_strongly_dom_component_safe_step + local.get_component_ok local.get_parent_parent_in_heap local.to_tree_order_ok local.to_tree_order_parent + local.to_tree_order_ptr_in_result local.to_tree_order_ptrs_in_heap returns_result_select_result) +qed +end + +interpretation i_get_component_get_parent?: l_get_component_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name first_in_tree_order get_attribute get_attribute_locs + by(auto simp add: l_get_component_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_get_parent\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \get\_root\_node\ + +locale l_get_component_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma get_root_node_is_strongly_dom_component_safe_step: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_root_node ptr' \\<^sub>r root" + shows "root \ set c \ ptr' \ set c" +proof + assume 1: "root \ set c" + obtain root_ptr where + root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + by (metis assms(4) bind_is_OK_E get_component_def is_OK_returns_result_I) + have "h \ get_root_node root \\<^sub>r root_ptr" + using "1" assms(1) assms(2) assms(3) assms(4) get_component_root_node_same root_ptr + by blast + moreover have "h \ get_root_node ptr' \\<^sub>r root_ptr" + by (metis (no_types, lifting) calculation assms(1) assms(2) assms(3) assms(5) + is_OK_returns_result_E local.get_root_node_root_in_heap local.to_tree_order_ok + local.to_tree_order_ptr_in_result local.to_tree_order_same_root select_result_I2) + ultimately have "h \ get_component ptr' \\<^sub>r c" + apply(auto simp add: get_component_def)[1] + by (smt "1" assms(1) assms(2) assms(3) assms(4) bind_pure_returns_result_I bind_returns_result_E3 + local.get_component_def local.get_component_subset local.get_root_node_pure) + then show "ptr' \ set c" + using assms(1) assms(2) assms(3) get_dom_component_ptr by blast +next + assume 1: "ptr' \ set c" + obtain root_ptr where + root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + by (metis assms(4) bind_is_OK_E get_component_def is_OK_returns_result_I) + have "h \ get_root_node ptr' \\<^sub>r root_ptr" + using "1" assms(1) assms(2) assms(3) assms(4) get_component_root_node_same root_ptr + by blast + then have "h \ get_root_node root \\<^sub>r root_ptr" + by (metis assms(1) assms(2) assms(3) assms(5) is_OK_returns_result_E local.get_root_node_root_in_heap + local.to_tree_order_ok local.to_tree_order_ptr_in_result local.to_tree_order_same_root returns_result_eq) + then have "h \ get_component ptr' \\<^sub>r c" + using "1" assms(1) assms(2) assms(3) assms(4) local.get_component_subset by blast + then show "root \ set c" + using assms(5) bind_returns_result_E3 local.get_component_def local.to_tree_order_ptr_in_result + by fastforce +qed + +lemma get_root_node_is_strongly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_root_node ptr \\<^sub>r root" + assumes "h \ get_root_node ptr \\<^sub>h h'" + shows "is_strongly_dom_component_safe {ptr} {root} h h'" +proof - + have "h = h'" + using assms(5) + by (meson local.get_root_node_pure pure_returns_heap_eq) + then show ?thesis + using assms + apply(auto simp add: is_strongly_dom_component_safe_def Let_def preserved_def)[1] + by (metis (no_types, lifting) IntI get_root_node_is_strongly_dom_component_safe_step is_OK_returns_result_I + local.get_component_impl local.get_component_ok local.get_dom_component_ptr + local.get_root_node_ptr_in_heap notin_fset returns_result_select_result) +qed +end + +interpretation i_get_component_get_root_node?: l_get_component_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name first_in_tree_order get_attribute get_attribute_locs + by(auto simp add: l_get_component_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \get\_element\_by\_id\ + +locale l_get_component_get_element_by_id\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma get_element_by_id_is_strongly_dom_component_safe_step: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_element_by_id ptr' idd \\<^sub>r Some result" + shows "cast result \ set c \ ptr' \ set c" +proof + assume 1: "cast result \ set c" + obtain root_ptr where + root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + by (metis assms(4) bind_is_OK_E get_component_def is_OK_returns_result_I) + then have "h \ to_tree_order root_ptr \\<^sub>r c" + using \h \ get_component ptr \\<^sub>r c\ + by (simp add: get_component_def bind_returns_result_E3) + + obtain to' where to': "h \ to_tree_order ptr' \\<^sub>r to'" + using \h \ get_element_by_id ptr' idd \\<^sub>r Some result\ + apply(simp add: get_element_by_id_def first_in_tree_order_def) + by (meson bind_is_OK_E is_OK_returns_result_I) + then have "cast result \ set to'" + using \h \ get_element_by_id ptr' idd \\<^sub>r Some result\ get_element_by_id_result_in_tree_order + by blast + + have "h \ get_root_node (cast result) \\<^sub>r root_ptr" + using "1" assms(1) assms(2) assms(3) assms(4) get_component_root_node_same root_ptr + by blast + then have "h \ get_root_node ptr' \\<^sub>r root_ptr" + using \cast result \ set to'\ \h \ to_tree_order ptr' \\<^sub>r to'\ + using "1" assms(1) assms(2) assms(3) assms(4) get_dom_component_ptr get_component_root_node_same + get_component_subset get_component_to_tree_order + by blast + then have "h \ get_component ptr' \\<^sub>r c" + using \h \ to_tree_order root_ptr \\<^sub>r c\ + using get_component_def by auto + then show "ptr' \ set c" + using assms(1) assms(2) assms(3) get_dom_component_ptr by blast +next + assume "ptr' \ set c" + moreover obtain to' where to': "h \ to_tree_order ptr' \\<^sub>r to'" + by (meson assms(1) assms(2) assms(3) assms(4) calculation get_dom_component_ptr_in_heap + get_component_subset is_OK_returns_result_E is_OK_returns_result_I to_tree_order_ok) + ultimately have "set to' \ set c" + using assms(1) assms(2) assms(3) assms(4) get_component_subset get_component_to_tree_order_subset + by blast + moreover have "cast result \ set to'" + using assms(5) get_element_by_id_result_in_tree_order to' by blast + ultimately show "cast result \ set c" + by blast +qed + + +lemma get_element_by_id_is_strongly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_element_by_id ptr idd \\<^sub>r Some result" + assumes "h \ get_element_by_id ptr idd \\<^sub>h h'" + shows "is_strongly_dom_component_safe {ptr} {cast result} h h'" +proof - + have "h = h'" + using assms(5) + by(auto simp add: preserved_def get_element_by_id_def first_in_tree_order_def + elim!: bind_returns_heap_E2 intro!: map_filter_M_pure bind_pure_I split: option.splits list.splits) + have "ptr |\| object_ptr_kinds h" + using assms(4) + apply(auto simp add: get_element_by_id_def)[1] + by (metis (no_types, lifting) assms(1) assms(2) assms(3) bind_is_OK_E is_OK_returns_result_I + local.first_in_tree_order_def local.to_tree_order_ptr_in_result local.to_tree_order_ptrs_in_heap) + obtain to where to: "h \ to_tree_order ptr \\<^sub>r to" + by (meson \ptr |\| object_ptr_kinds h\ assms(1) assms(2) assms(3) is_OK_returns_result_E + local.to_tree_order_ok) + then have "cast result \ set to" + using assms(4) local.get_element_by_id_result_in_tree_order by auto + obtain c where c: "h \ a_get_component ptr \\<^sub>r c" + using \ptr |\| object_ptr_kinds h\ assms(1) assms(2) assms(3) local.get_component_impl + local.get_component_ok + by blast + + then show ?thesis + using assms \h = h'\ + apply(auto simp add: is_strongly_dom_component_safe_def Let_def preserved_def get_element_by_id_def + first_in_tree_order_def elim!: bind_returns_result_E2 intro!: map_filter_M_pure bind_pure_I + split: option.splits list.splits)[1] + by (metis (no_types, lifting) Int_iff \ptr |\| object_ptr_kinds h\ assms(4) finite_set_in + get_element_by_id_is_strongly_dom_component_safe_step local.get_component_impl local.get_dom_component_ptr + select_result_I2) +qed +end + +interpretation i_get_component_get_element_by_id?: l_get_component_get_element_by_id\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name first_in_tree_order get_attribute get_attribute_locs + by(auto simp add: l_get_component_get_element_by_id\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_get_element_by_id\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \get\_elements\_by\_class\_name\ + +locale l_get_component_get_elements_by_class_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma get_elements_by_class_name_result_in_tree_order: + assumes "h \ get_elements_by_class_name ptr name \\<^sub>r results" + assumes "h \ to_tree_order ptr \\<^sub>r to" + assumes "result \ set results" + shows "cast result \ set to" + using assms + by(auto simp add: get_elements_by_class_name_def first_in_tree_order_def + elim!: map_filter_M_pure_E[where y=result] bind_returns_result_E2 + dest!: bind_returns_result_E3[rotated, OF assms(2), rotated] + intro!: map_filter_M_pure map_M_pure_I bind_pure_I + split: option.splits list.splits if_splits) + +lemma get_elements_by_class_name_is_strongly_dom_component_safe_step: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_elements_by_class_name ptr' name \\<^sub>r results" + assumes "result \ set results" + shows "cast result \ set c \ ptr' \ set c" +proof + assume 1: "cast result \ set c" + obtain root_ptr where + root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + by (metis assms(4) bind_is_OK_E get_component_def is_OK_returns_result_I) + then have "h \ to_tree_order root_ptr \\<^sub>r c" + using \h \ get_component ptr \\<^sub>r c\ + by (simp add: get_component_def bind_returns_result_E3) + + obtain to' where to': "h \ to_tree_order ptr' \\<^sub>r to'" + using \h \ get_elements_by_class_name ptr' name \\<^sub>r results\ + apply(simp add: get_elements_by_class_name_def first_in_tree_order_def) + by (meson bind_is_OK_E is_OK_returns_result_I) + then have "cast result \ set to'" + using get_elements_by_class_name_result_in_tree_order assms by blast + + have "h \ get_root_node (cast result) \\<^sub>r root_ptr" + using "1" assms(1) assms(2) assms(3) assms(4) get_component_root_node_same root_ptr + by blast + then have "h \ get_root_node ptr' \\<^sub>r root_ptr" + using \cast result \ set to'\ \h \ to_tree_order ptr' \\<^sub>r to'\ + using "1" assms(1) assms(2) assms(3) assms(4) get_dom_component_ptr get_component_root_node_same + get_component_subset get_component_to_tree_order + by blast + then have "h \ get_component ptr' \\<^sub>r c" + using \h \ to_tree_order root_ptr \\<^sub>r c\ + using get_component_def by auto + then show "ptr' \ set c" + using assms(1) assms(2) assms(3) get_dom_component_ptr by blast +next + assume "ptr' \ set c" + moreover obtain to' where to': "h \ to_tree_order ptr' \\<^sub>r to'" + by (meson assms(1) assms(2) assms(3) assms(4) calculation get_dom_component_ptr_in_heap + get_component_subset is_OK_returns_result_E is_OK_returns_result_I to_tree_order_ok) + ultimately have "set to' \ set c" + using assms(1) assms(2) assms(3) assms(4) get_component_subset get_component_to_tree_order_subset + by blast + moreover have "cast result \ set to'" + using assms get_elements_by_class_name_result_in_tree_order to' by blast + ultimately show "cast result \ set c" + by blast +qed + +lemma get_elements_by_class_name_pure [simp]: + "pure (get_elements_by_class_name ptr name) h" + by(auto simp add: get_elements_by_class_name_def intro!: bind_pure_I map_filter_M_pure + split: option.splits) + +lemma get_elements_by_class_name_is_strongly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_elements_by_class_name ptr name \\<^sub>r results" + assumes "h \ get_elements_by_class_name ptr name \\<^sub>h h'" + shows "is_strongly_dom_component_safe {ptr} (cast ` set results) h h'" +proof - + have "h = h'" + using assms(5) + by (meson get_elements_by_class_name_pure pure_returns_heap_eq) + have "ptr |\| object_ptr_kinds h" + using assms(4) + apply(auto simp add: get_elements_by_class_name_def)[1] + by (metis (no_types, lifting) assms(1) assms(2) assms(3) bind_is_OK_E is_OK_returns_result_I + local.first_in_tree_order_def local.to_tree_order_ptr_in_result local.to_tree_order_ptrs_in_heap) + obtain to where to: "h \ to_tree_order ptr \\<^sub>r to" + by (meson \ptr |\| object_ptr_kinds h\ assms(1) assms(2) assms(3) is_OK_returns_result_E + local.to_tree_order_ok) + then have "cast ` set results \ set to" + using assms(4) local.get_elements_by_class_name_result_in_tree_order by auto + obtain c where c: "h \ a_get_component ptr \\<^sub>r c" + using \ptr |\| object_ptr_kinds h\ assms(1) assms(2) assms(3) local.get_component_impl local.get_component_ok + by blast + + then show ?thesis + using assms \h = h'\ + apply(auto simp add: is_strongly_dom_component_safe_def Let_def preserved_def + get_elements_by_class_name_def first_in_tree_order_def elim!: bind_returns_result_E2 + intro!: map_filter_M_pure bind_pure_I split: option.splits list.splits)[1] + by (metis (no_types, lifting) Int_iff \ptr |\| object_ptr_kinds h\ assms(4) finite_set_in + get_elements_by_class_name_is_strongly_dom_component_safe_step local.get_component_impl + local.get_dom_component_ptr select_result_I2) +qed +end + +interpretation i_get_component_get_elements_by_class_name?: l_get_component_get_elements_by_class_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name first_in_tree_order get_attribute get_attribute_locs + by(auto simp add: l_get_component_get_elements_by_class_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_get_elements_by_class_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + + +subsection \get\_elements\_by\_tag\_name\ + +locale l_get_component_get_elements_by_tag_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_first_in_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_to_tree_order\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_element_by\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma get_elements_by_tag_name_result_in_tree_order: + assumes "h \ get_elements_by_tag_name ptr name \\<^sub>r results" + assumes "h \ to_tree_order ptr \\<^sub>r to" + assumes "result \ set results" + shows "cast result \ set to" + using assms + by(auto simp add: get_elements_by_tag_name_def first_in_tree_order_def + elim!: map_filter_M_pure_E[where y=result] bind_returns_result_E2 + dest!: bind_returns_result_E3[rotated, OF assms(2), rotated] + intro!: map_filter_M_pure map_M_pure_I bind_pure_I + split: option.splits list.splits if_splits) + +lemma get_elements_by_tag_name_is_strongly_dom_component_safe_step: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_component ptr \\<^sub>r c" + assumes "h \ get_elements_by_tag_name ptr' name \\<^sub>r results" + assumes "result \ set results" + shows "cast result \ set c \ ptr' \ set c" +proof + assume 1: "cast result \ set c" + obtain root_ptr where + root_ptr: "h \ get_root_node ptr \\<^sub>r root_ptr" + by (metis assms(4) bind_is_OK_E get_component_def is_OK_returns_result_I) + then have "h \ to_tree_order root_ptr \\<^sub>r c" + using \h \ get_component ptr \\<^sub>r c\ + by (simp add: get_component_def bind_returns_result_E3) + + obtain to' where to': "h \ to_tree_order ptr' \\<^sub>r to'" + using \h \ get_elements_by_tag_name ptr' name \\<^sub>r results\ + apply(simp add: get_elements_by_tag_name_def first_in_tree_order_def) + by (meson bind_is_OK_E is_OK_returns_result_I) + then have "cast result \ set to'" + using get_elements_by_tag_name_result_in_tree_order assms by blast + + have "h \ get_root_node (cast result) \\<^sub>r root_ptr" + using "1" assms(1) assms(2) assms(3) assms(4) get_component_root_node_same root_ptr + by blast + then have "h \ get_root_node ptr' \\<^sub>r root_ptr" + using \cast result \ set to'\ \h \ to_tree_order ptr' \\<^sub>r to'\ + using "1" assms(1) assms(2) assms(3) assms(4) get_dom_component_ptr get_component_root_node_same + get_component_subset get_component_to_tree_order + by blast + then have "h \ get_component ptr' \\<^sub>r c" + using \h \ to_tree_order root_ptr \\<^sub>r c\ + using get_component_def by auto + then show "ptr' \ set c" + using assms(1) assms(2) assms(3) get_dom_component_ptr by blast +next + assume "ptr' \ set c" + moreover obtain to' where to': "h \ to_tree_order ptr' \\<^sub>r to'" + by (meson assms(1) assms(2) assms(3) assms(4) calculation get_dom_component_ptr_in_heap + get_component_subset is_OK_returns_result_E is_OK_returns_result_I to_tree_order_ok) + ultimately have "set to' \ set c" + using assms(1) assms(2) assms(3) assms(4) get_component_subset get_component_to_tree_order_subset + by blast + moreover have "cast result \ set to'" + using assms get_elements_by_tag_name_result_in_tree_order to' by blast + ultimately show "cast result \ set c" + by blast +qed + +lemma get_elements_by_tag_name_is_strongly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_elements_by_tag_name ptr name \\<^sub>r results" + assumes "h \ get_elements_by_tag_name ptr name \\<^sub>h h'" + shows "is_strongly_dom_component_safe {ptr} (cast ` set results) h h'" +proof - + have "h = h'" + using assms(5) + by (meson get_elements_by_tag_name_pure pure_returns_heap_eq) + have "ptr |\| object_ptr_kinds h" + using assms(4) + apply(auto simp add: get_elements_by_tag_name_def)[1] + by (metis (no_types, lifting) assms(1) assms(2) assms(3) bind_is_OK_E is_OK_returns_result_I + local.first_in_tree_order_def local.to_tree_order_ptr_in_result local.to_tree_order_ptrs_in_heap) + obtain to where to: "h \ to_tree_order ptr \\<^sub>r to" + by (meson \ptr |\| object_ptr_kinds h\ assms(1) assms(2) assms(3) is_OK_returns_result_E + local.to_tree_order_ok) + then have "cast ` set results \ set to" + using assms(4) local.get_elements_by_tag_name_result_in_tree_order by auto + obtain c where c: "h \ a_get_component ptr \\<^sub>r c" + using \ptr |\| object_ptr_kinds h\ assms(1) assms(2) assms(3) local.get_component_impl local.get_component_ok + by blast + + then show ?thesis + using assms \h = h'\ + apply(auto simp add: is_strongly_dom_component_safe_def Let_def preserved_def + get_elements_by_class_name_def first_in_tree_order_def elim!: bind_returns_result_E2 + intro!: map_filter_M_pure bind_pure_I split: option.splits list.splits)[1] + by (metis (no_types, lifting) IntI \ptr |\| object_ptr_kinds h\ finite_set_in + get_elements_by_tag_name_is_strongly_dom_component_safe_step local.get_component_impl + local.get_dom_component_ptr select_result_I2) +qed +end + +interpretation i_get_component_get_elements_by_tag_name?: l_get_component_get_elements_by_tag_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name first_in_tree_order get_attribute get_attribute_locs + by(auto simp add: l_get_component_get_elements_by_tag_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_get_elements_by_tag_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \remove\_child\ + +lemma remove_child_not_strongly_dom_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" and + h' and ptr and child where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ remove_child ptr child \\<^sub>h h'" and + "\ is_strongly_dom_component_safe { ptr, cast child} {} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + e1 \ create_element document_ptr ''div''; + e2 \ create_element document_ptr ''div''; + append_child (cast e1) (cast e2); + return (e1, e2) + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e1 = "fst |?h0 \ ?P|\<^sub>r" + let ?e2 = "snd |?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and ptr="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e1" and child="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e2"]) + by code_simp+ +qed + + +subsection \adopt\_node\ + +lemma adopt_node_not_strongly_dom_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" and + h' and document_ptr and child where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ adopt_node document_ptr child \\<^sub>h h'" and + "\ is_strongly_dom_component_safe {cast document_ptr, cast child} {} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + document_ptr2 \ create_document; + e1 \ create_element document_ptr ''div''; + adopt_node document_ptr2 (cast e1); + return (document_ptr, e1) + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?document_ptr = "fst |?h0 \ ?P|\<^sub>r" + let ?e1 = "snd |?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and document_ptr="?document_ptr" and child="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e1"]) + by code_simp+ +qed + +subsection \create\_element\ + +lemma create_element_not_strongly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" and + h' and document_ptr and new_element_ptr and tag where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ create_element document_ptr tag \\<^sub>r new_element_ptr \\<^sub>h h'" and + "\ is_strongly_dom_component_safe {cast document_ptr} {cast new_element_ptr} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" + let ?P = "create_document" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?document_ptr = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and document_ptr="?document_ptr"]) + by code_simp+ +qed + + +locale l_get_component_create_element\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order + get_parent get_parent_locs get_child_nodes get_child_nodes_locs get_component + is_strongly_dom_component_safe is_weakly_dom_component_safe get_root_node get_root_node_locs + get_ancestors get_ancestors_locs get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id + get_elements_by_class_name get_elements_by_tag_name + + l_create_element\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes + set_disconnected_nodes_locs set_tag_name set_tag_name_locs type_wf create_element known_ptr + + l_get_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_disconnected_nodes get_disconnected_nodes_locs + + l_set_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_disconnected_nodes set_disconnected_nodes_locs + + l_set_tag_name\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_tag_name set_tag_name_locs + + l_new_element_get_child_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf known_ptr get_child_nodes get_child_nodes_locs + + l_new_element_get_disconnected_nodes get_disconnected_nodes get_disconnected_nodes_locs + + l_set_tag_name_get_child_nodes type_wf set_tag_name set_tag_name_locs known_ptr + get_child_nodes get_child_nodes_locs + + l_set_tag_name_get_disconnected_nodes type_wf set_tag_name set_tag_name_locs + get_disconnected_nodes get_disconnected_nodes_locs + + l_set_disconnected_nodes type_wf set_disconnected_nodes set_disconnected_nodes_locs + + l_set_disconnected_nodes_get_child_nodes set_disconnected_nodes set_disconnected_nodes_locs + get_child_nodes get_child_nodes_locs + + l_set_disconnected_nodes_get_disconnected_nodes type_wf get_disconnected_nodes + get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs + + l_new_element type_wf + + l_create_element_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr known_ptrs type_wf get_child_nodes get_child_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs heap_is_wellformed parent_child_rel set_tag_name + set_tag_name_locs set_disconnected_nodes set_disconnected_nodes_locs + create_element + for known_ptr :: "(_::linorder) object_ptr \ bool" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and type_wf :: "(_) heap \ bool" + and known_ptrs :: "(_) heap \ bool" + and to_tree_order :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_parent :: "(_) node_ptr \ ((_) heap, exception, (_) object_ptr option) prog" + and get_parent_locs :: "((_) heap \ (_) heap \ bool) set" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_component :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and is_strongly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + and is_weakly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + and get_root_node :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_locs :: "((_) heap \ (_) heap \ bool) set" + and get_ancestors :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_ancestors_locs :: "((_) heap \ (_) heap \ bool) set" + and get_element_by_id :: "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr option) prog" + and get_elements_by_class_name :: "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr list) prog" + and get_elements_by_tag_name :: "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr list) prog" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and set_disconnected_nodes :: "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and set_tag_name :: "(_) element_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_tag_name_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and create_element :: "(_) document_ptr \ char list \ ((_) heap, exception, (_) element_ptr) prog" +begin + +lemma create_element_is_weakly_dom_component_safe_step: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ create_element document_ptr tag \\<^sub>h h'" + assumes "ptr \ set |h \ get_component (cast document_ptr)|\<^sub>r" + assumes "ptr \ cast |h \ create_element document_ptr tag|\<^sub>r" + shows "preserved (get_M ptr getter) h h'" +proof - + obtain new_element_ptr h2 h3 disc_nodes where + new_element_ptr: "h \ new_element \\<^sub>r new_element_ptr" and + h2: "h \ new_element \\<^sub>h h2" and + h3: "h2 \set_tag_name new_element_ptr tag \\<^sub>h h3" and + disc_nodes: "h3 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes" and + h': "h3 \ set_disconnected_nodes document_ptr (cast new_element_ptr # disc_nodes) \\<^sub>h h'" + using assms(4) + by(auto simp add: create_element_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated]) + have "h \ create_element document_ptr tag \\<^sub>r new_element_ptr" + using new_element_ptr h2 h3 disc_nodes h' + apply(auto simp add: create_element_def intro!: bind_returns_result_I + bind_pure_returns_result_I[OF get_disconnected_nodes_pure])[1] + apply (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + by (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + have "preserved (get_M ptr getter) h h2" + using h2 new_element_ptr + apply(rule new_element_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t) + using new_element_ptr assms(6) \h \ create_element document_ptr tag \\<^sub>r new_element_ptr\ + by simp + + have "preserved (get_M ptr getter) h2 h3" + using set_tag_name_writes h3 + apply(rule reads_writes_preserved2) + apply(auto simp add: set_tag_name_locs_impl a_set_tag_name_locs_def all_args_def)[1] + by (metis (no_types, lifting) \h \ create_element document_ptr tag \\<^sub>r new_element_ptr\ assms(6) + get_M_Element_preserved8 select_result_I2) + + have "document_ptr |\| document_ptr_kinds h" + using create_element_document_in_heap + using assms(4) + by blast + then + have "ptr \ (cast document_ptr)" + using assms(5) assms(1) assms(2) assms(3) local.get_component_ok local.get_dom_component_ptr + by auto + have "preserved (get_M ptr getter) h3 h'" + using set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved2) + apply(auto simp add: set_disconnected_nodes_locs_def all_args_def)[1] + by (metis \ptr \ cast\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r document_ptr\ get_M_Mdocument_preserved3) + + show ?thesis + using \preserved (get_M ptr getter) h h2\ \preserved (get_M ptr getter) h2 h3\ + \preserved (get_M ptr getter) h3 h'\ + by(auto simp add: preserved_def) +qed + + +lemma create_element_is_weakly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ create_element document_ptr tag \\<^sub>r result \\<^sub>h h'" + shows "is_weakly_dom_component_safe {cast document_ptr} {cast result} h h'" +proof - + obtain new_element_ptr h2 h3 disc_nodes_h3 where + new_element_ptr: "h \ new_element \\<^sub>r new_element_ptr" and + h2: "h \ new_element \\<^sub>h h2" and + h3: "h2 \ set_tag_name new_element_ptr tag \\<^sub>h h3" and + disc_nodes_h3: "h3 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" and + h': "h3 \ set_disconnected_nodes document_ptr (cast new_element_ptr # disc_nodes_h3) \\<^sub>h h'" + using assms(4) + by(auto simp add: create_element_def returns_result_heap_def + elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated] ) + then have "h \ create_element document_ptr tag \\<^sub>r new_element_ptr" + apply(auto simp add: create_element_def intro!: bind_returns_result_I)[1] + apply (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + apply (metis is_OK_returns_heap_E is_OK_returns_result_I local.get_disconnected_nodes_pure + pure_returns_heap_eq) + by (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + have "h \ create_element document_ptr tag \\<^sub>h h'" + by (meson assms(4) returns_result_heap_def) + + + have "new_element_ptr \ set |h \ element_ptr_kinds_M|\<^sub>r" + using new_element_ptr ElementMonad.ptr_kinds_ptr_kinds_M h2 + using new_element_ptr_not_in_heap by blast + then have "cast new_element_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r" + by simp + then have "cast new_element_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r" + by simp + + have object_ptr_kinds_eq_h: "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_element_ptr|}" + using new_element_new_ptr h2 new_element_ptr by blast + then have node_ptr_kinds_eq_h: "node_ptr_kinds h2 = node_ptr_kinds h |\| {|cast new_element_ptr|}" + apply(simp add: node_ptr_kinds_def) + by force + then have element_ptr_kinds_eq_h: "element_ptr_kinds h2 = element_ptr_kinds h |\| {|new_element_ptr|}" + apply(simp add: element_ptr_kinds_def) + by force + have character_data_ptr_kinds_eq_h: "character_data_ptr_kinds h2 = character_data_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: node_ptr_kinds_def character_data_ptr_kinds_def) + have document_ptr_kinds_eq_h: "document_ptr_kinds h2 = document_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: document_ptr_kinds_def) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h3 = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_tag_name_writes h3]) + using set_tag_name_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h2: "document_ptr_kinds h3 = document_ptr_kinds h2" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h2: "node_ptr_kinds h3 = node_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h' = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_disconnected_nodes_writes h']) + using set_disconnected_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h3: "document_ptr_kinds h' = document_ptr_kinds h3" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h3: "node_ptr_kinds h' = node_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: node_ptr_kinds_def) + + have "known_ptr (cast new_element_ptr)" + using \h \ create_element document_ptr tag \\<^sub>r new_element_ptr\ local.create_element_known_ptr + by blast + then + have "known_ptrs h2" + using known_ptrs_new_ptr object_ptr_kinds_eq_h \known_ptrs h\ h2 + by blast + then + have "known_ptrs h3" + using known_ptrs_preserved object_ptr_kinds_eq_h2 by blast + then + have "known_ptrs h'" + using known_ptrs_preserved object_ptr_kinds_eq_h3 by blast + + + have "document_ptr |\| document_ptr_kinds h" + using disc_nodes_h3 document_ptr_kinds_eq_h object_ptr_kinds_eq_h2 + get_disconnected_nodes_ptr_in_heap \type_wf h\ document_ptr_kinds_def + by (metis is_OK_returns_result_I) + + have children_eq_h: "\(ptr'::(_) object_ptr) children. ptr' \ cast new_element_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads h2 get_child_nodes_new_element[rotated, OF new_element_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h: "\ptr'. ptr' \ cast new_element_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + + have "h2 \ get_child_nodes (cast new_element_ptr) \\<^sub>r []" + using new_element_ptr h2 new_element_ptr_in_heap[OF h2 new_element_ptr] + new_element_is_element_ptr[OF new_element_ptr] new_element_no_child_nodes + by blast + have disconnected_nodes_eq_h: + "\doc_ptr disc_nodes. h \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads h2 get_disconnected_nodes_new_element[OF new_element_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have disconnected_nodes_eq2_h: + "\doc_ptr. |h \ get_disconnected_nodes doc_ptr|\<^sub>r = |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have children_eq_h2: + "\ptr' children. h2 \ get_child_nodes ptr' \\<^sub>r children = h3 \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads set_tag_name_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_tag_name_get_child_nodes) + then have children_eq2_h2: "\ptr'. |h2 \ get_child_nodes ptr'|\<^sub>r = |h3 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h2: + "\doc_ptr disc_nodes. h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_tag_name_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_tag_name_get_disconnected_nodes) + then have disconnected_nodes_eq2_h2: + "\doc_ptr. |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have "type_wf h2" + using \type_wf h\ new_element_types_preserved h2 by blast + then have "type_wf h3" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_tag_name_writes h3] + using set_tag_name_types_preserved + by(auto simp add: reflp_def transp_def) + then have "type_wf h'" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_disconnected_nodes_writes h'] + using set_disconnected_nodes_types_preserved + by(auto simp add: reflp_def transp_def) + + have children_eq_h3: + "\ptr' children. h3 \ get_child_nodes ptr' \\<^sub>r children = h' \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_child_nodes) + then have children_eq2_h3: "\ptr'. |h3 \ get_child_nodes ptr'|\<^sub>r = |h' \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h3: + "\doc_ptr disc_nodes. document_ptr \ doc_ptr + \ h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_disconnected_nodes_different_pointers) + then have disconnected_nodes_eq2_h3: + "\doc_ptr. document_ptr \ doc_ptr + \ |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have disc_nodes_document_ptr_h2: "h2 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" + using disconnected_nodes_eq_h2 disc_nodes_h3 by auto + then have disc_nodes_document_ptr_h: "h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" + using disconnected_nodes_eq_h by auto + then have "cast new_element_ptr \ set disc_nodes_h3" + using \heap_is_wellformed h\ + using \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ + a_all_ptrs_in_heap_def heap_is_wellformed_def + using NodeMonad.ptr_kinds_ptr_kinds_M local.heap_is_wellformed_disc_nodes_in_heap by blast + + + have "parent_child_rel h = parent_child_rel h'" + proof - + have "parent_child_rel h = parent_child_rel h2" + proof(auto simp add: parent_child_rel_def)[1] + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h2" + by (simp add: object_ptr_kinds_eq_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "x \ set |h2 \ get_child_nodes a|\<^sub>r" + by (metis ObjectMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ children_eq2_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h" + using object_ptr_kinds_eq_h \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr) \\<^sub>r []\ + by(auto) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "x \ set |h \ get_child_nodes a|\<^sub>r" + by (metis (no_types, lifting) + \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr) \\<^sub>r []\ + children_eq2_h empty_iff empty_set image_eqI select_result_I2) + qed + also have "\ = parent_child_rel h3" + by(auto simp add: parent_child_rel_def object_ptr_kinds_eq_h2 children_eq2_h2) + also have "\ = parent_child_rel h'" + by(auto simp add: parent_child_rel_def object_ptr_kinds_eq_h3 children_eq2_h3) + finally show ?thesis + by simp + qed + have root: "h \ get_root_node (cast document_ptr) \\<^sub>r cast document_ptr" + by (simp add: \document_ptr |\| document_ptr_kinds h\ local.get_root_node_not_node_same) + then + have root': "h' \ get_root_node (cast document_ptr) \\<^sub>r cast document_ptr" + by (simp add: \document_ptr |\| document_ptr_kinds h\ document_ptr_kinds_eq_h + local.get_root_node_not_node_same object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3) + + + have "heap_is_wellformed h'" + using create_element_preserves_wellformedness assms returns_result_heap_def + by metis + + have "cast result |\| object_ptr_kinds h" + using \cast new_element_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ returns_result_heap_def + by (metis (full_types) ObjectMonad.ptr_kinds_ptr_kinds_M + \h \ create_element document_ptr tag \\<^sub>r new_element_ptr\ assms(4) returns_result_eq) + + obtain to where to: "h \ to_tree_order (cast document_ptr) \\<^sub>r to" + by (meson \document_ptr |\| document_ptr_kinds h\ assms(1) assms(2) assms(3) + document_ptr_kinds_commutes is_OK_returns_result_E local.to_tree_order_ok) + then + have "h \ a_get_component (cast document_ptr) \\<^sub>r to" + using root + by(auto simp add: a_get_component_def) + moreover + obtain to' where to': "h' \ to_tree_order (cast document_ptr) \\<^sub>r to'" + by (meson \heap_is_wellformed h'\ \known_ptrs h'\ \type_wf h'\ is_OK_returns_result_E + local.get_root_node_root_in_heap local.to_tree_order_ok root') + then + have "h' \ a_get_component (cast document_ptr) \\<^sub>r to'" + using root' + by(auto simp add: a_get_component_def) + moreover + have "\child. child \ set to \ child \ set to'" + by (metis \heap_is_wellformed h'\ \known_ptrs h'\ \parent_child_rel h = parent_child_rel h'\ + \type_wf h'\ assms(1) assms(2) assms(3) local.to_tree_order_parent_child_rel to to') + ultimately + have "set |h \ local.a_get_component (cast document_ptr)|\<^sub>r = set |h' \ local.a_get_component (cast document_ptr)|\<^sub>r" + by(auto simp add: a_get_component_def) + + show ?thesis + apply(auto simp add: is_weakly_dom_component_safe_def Let_def)[1] + apply (metis \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr) \\<^sub>r []\ assms(2) assms(3) + children_eq_h local.get_child_nodes_ok local.get_child_nodes_ptr_in_heap local.known_ptrs_known_ptr + object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3 returns_result_select_result) + apply (metis \h \ create_element document_ptr tag \\<^sub>r new_element_ptr\ assms(4) + element_ptr_kinds_commutes h2 new_element_ptr new_element_ptr_in_heap node_ptr_kinds_eq_h2 + node_ptr_kinds_eq_h3 returns_result_eq returns_result_heap_def) + using \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r result |\| object_ptr_kinds h\ element_ptr_kinds_commutes + node_ptr_kinds_commutes apply blast + using assms(1) assms(2) assms(3) \h \ create_element document_ptr tag \\<^sub>h h'\ + apply(rule create_element_is_weakly_dom_component_safe_step) + apply (simp add: local.get_component_impl) + using \cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_element_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ + \h \ create_element document_ptr tag \\<^sub>r new_element_ptr\ by auto +qed +end + +interpretation i_get_component_create_element?: l_get_component_create_element\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + known_ptr heap_is_wellformed parent_child_rel type_wf known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_element_by_id get_elements_by_class_name get_elements_by_tag_name get_disconnected_nodes + get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs set_tag_name + set_tag_name_locs create_element + by(auto simp add: l_get_component_create_element\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_create_element\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + + +subsection \create\_character\_data\ + +lemma create_character_data_not_strongly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" and + h' and document_ptr and new_character_data_ptr and val where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ create_character_data document_ptr val \\<^sub>r new_character_data_ptr \\<^sub>h h'" and + "\ is_strongly_dom_component_safe {cast document_ptr} {cast new_character_data_ptr} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" + let ?P = "create_document" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?document_ptr = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and document_ptr="?document_ptr"]) + by code_simp+ +qed + +locale l_get_component_create_character_data\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order + get_parent get_parent_locs get_child_nodes get_child_nodes_locs get_component + is_strongly_dom_component_safe is_weakly_dom_component_safe get_root_node get_root_node_locs + get_ancestors get_ancestors_locs get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id + get_elements_by_class_name get_elements_by_tag_name + + l_create_character_data\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes + set_disconnected_nodes_locs set_val set_val_locs type_wf create_character_data known_ptr + + l_get_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf get_disconnected_nodes get_disconnected_nodes_locs + + l_set_disconnected_nodes\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_disconnected_nodes set_disconnected_nodes_locs + + l_set_val\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_val set_val_locs + + l_create_character_data_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr type_wf get_child_nodes get_child_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs heap_is_wellformed parent_child_rel set_val + set_val_locs set_disconnected_nodes set_disconnected_nodes_locs + create_character_data known_ptrs + for known_ptr :: "(_::linorder) object_ptr \ bool" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and type_wf :: "(_) heap \ bool" + and known_ptrs :: "(_) heap \ bool" + and to_tree_order :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_parent :: "(_) node_ptr \ ((_) heap, exception, (_) object_ptr option) prog" + and get_parent_locs :: "((_) heap \ (_) heap \ bool) set" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_component :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and is_strongly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + and is_weakly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + and get_root_node :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_locs :: "((_) heap \ (_) heap \ bool) set" + and get_ancestors :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_ancestors_locs :: "((_) heap \ (_) heap \ bool) set" + and get_element_by_id :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr option) prog" + and get_elements_by_class_name :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr list) prog" + and get_elements_by_tag_name :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr list) prog" + and set_val :: "(_) character_data_ptr \ char list \ ((_) heap, exception, unit) prog" + and set_val_locs :: "(_) character_data_ptr \ ((_) heap, exception, unit) prog set" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and set_disconnected_nodes :: "(_) document_ptr \ (_) node_ptr list \ ((_) heap, exception, unit) prog" + and set_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap, exception, unit) prog set" + and create_character_data :: + "(_) document_ptr \ char list \ ((_) heap, exception, (_) character_data_ptr) prog" +begin + +lemma create_character_data_is_weakly_dom_component_safe_step: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ create_character_data document_ptr text \\<^sub>h h'" + assumes "ptr \ set |h \ get_component (cast document_ptr)|\<^sub>r" + assumes "ptr \ cast |h \ create_character_data document_ptr text|\<^sub>r" + shows "preserved (get_M ptr getter) h h'" +proof - + obtain new_character_data_ptr h2 h3 disc_nodes where + new_character_data_ptr: "h \ new_character_data \\<^sub>r new_character_data_ptr" and + h2: "h \ new_character_data \\<^sub>h h2" and + h3: "h2 \ set_val new_character_data_ptr text \\<^sub>h h3" and + disc_nodes: "h3 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes" and + h': "h3 \ set_disconnected_nodes document_ptr (cast new_character_data_ptr # disc_nodes) \\<^sub>h h'" + using assms(4) + by(auto simp add: create_character_data_def + elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated]) + + have "h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr" + using new_character_data_ptr h2 h3 disc_nodes h' + apply(auto simp add: create_character_data_def + intro!: bind_returns_result_I bind_pure_returns_result_I[OF get_disconnected_nodes_pure])[1] + apply (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + by (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + have "preserved (get_M ptr getter) h h2" + using h2 new_character_data_ptr + apply(rule new_character_data_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t) + using new_character_data_ptr assms(6) + \h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr\ + by simp + + have "preserved (get_M ptr getter) h2 h3" + using set_val_writes h3 + apply(rule reads_writes_preserved2) + apply(auto simp add: set_val_locs_impl a_set_val_locs_def all_args_def)[1] + by (metis (mono_tags) CharacterData_simp11 + \h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr\ assms(4) assms(6) + is_OK_returns_heap_I is_OK_returns_result_E returns_result_eq select_result_I2) + + have "document_ptr |\| document_ptr_kinds h" + using create_character_data_document_in_heap + using assms(4) + by blast + then + have "ptr \ (cast document_ptr)" + using assms(5) assms(1) assms(2) assms(3) local.get_component_ok local.get_dom_component_ptr + by auto + have "preserved (get_M ptr getter) h3 h'" + using set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved2) + apply(auto simp add: set_disconnected_nodes_locs_def all_args_def)[1] + by (metis \ptr \ cast\<^sub>d\<^sub>o\<^sub>c\<^sub>u\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r document_ptr\ get_M_Mdocument_preserved3) + + show ?thesis + using \preserved (get_M ptr getter) h h2\ \preserved (get_M ptr getter) h2 h3\ + \preserved (get_M ptr getter) h3 h'\ + by(auto simp add: preserved_def) +qed + +lemma create_character_data_is_weakly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ create_character_data document_ptr text \\<^sub>r result" + assumes "h \ create_character_data document_ptr text \\<^sub>h h'" + shows "is_weakly_dom_component_safe {cast document_ptr} {cast result} h h'" +proof - + + obtain new_character_data_ptr h2 h3 disc_nodes_h3 where + new_character_data_ptr: "h \ new_character_data \\<^sub>r new_character_data_ptr" and + h2: "h \ new_character_data \\<^sub>h h2" and + h3: "h2 \ set_val new_character_data_ptr text \\<^sub>h h3" and + disc_nodes_h3: "h3 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" and + h': "h3 \ set_disconnected_nodes document_ptr (cast new_character_data_ptr # disc_nodes_h3) \\<^sub>h h'" + using assms(5) + by(auto simp add: create_character_data_def + elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_disconnected_nodes_pure, rotated] ) + then + have "h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr" + apply(auto simp add: create_character_data_def intro!: bind_returns_result_I)[1] + apply (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + apply (metis is_OK_returns_heap_E is_OK_returns_result_I local.get_disconnected_nodes_pure + pure_returns_heap_eq) + by (metis is_OK_returns_heap_I is_OK_returns_result_E old.unit.exhaust) + + have "new_character_data_ptr \ set |h \ character_data_ptr_kinds_M|\<^sub>r" + using new_character_data_ptr CharacterDataMonad.ptr_kinds_ptr_kinds_M h2 + using new_character_data_ptr_not_in_heap by blast + then have "cast new_character_data_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r" + by simp + then have "cast new_character_data_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r" + by simp + + + + have object_ptr_kinds_eq_h: + "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_character_data_ptr|}" + using new_character_data_new_ptr h2 new_character_data_ptr by blast + then have node_ptr_kinds_eq_h: + "node_ptr_kinds h2 = node_ptr_kinds h |\| {|cast new_character_data_ptr|}" + apply(simp add: node_ptr_kinds_def) + by force + then have character_data_ptr_kinds_eq_h: + "character_data_ptr_kinds h2 = character_data_ptr_kinds h |\| {|new_character_data_ptr|}" + apply(simp add: character_data_ptr_kinds_def) + by force + have element_ptr_kinds_eq_h: "element_ptr_kinds h2 = element_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: node_ptr_kinds_def element_ptr_kinds_def) + have document_ptr_kinds_eq_h: "document_ptr_kinds h2 = document_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: document_ptr_kinds_def) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h3 = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_val_writes h3]) + using set_val_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h2: "document_ptr_kinds h3 = document_ptr_kinds h2" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h2: "node_ptr_kinds h3 = node_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h' = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_disconnected_nodes_writes h']) + using set_disconnected_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h3: "document_ptr_kinds h' = document_ptr_kinds h3" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h3: "node_ptr_kinds h' = node_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: node_ptr_kinds_def) + + + have "document_ptr |\| document_ptr_kinds h" + using disc_nodes_h3 document_ptr_kinds_eq_h object_ptr_kinds_eq_h2 + get_disconnected_nodes_ptr_in_heap \type_wf h\ document_ptr_kinds_def + by (metis is_OK_returns_result_I) + + have children_eq_h: "\(ptr'::(_) object_ptr) children. ptr' \ cast new_character_data_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads h2 get_child_nodes_new_character_data[rotated, OF new_character_data_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h: + "\ptr'. ptr' \ cast new_character_data_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have object_ptr_kinds_eq_h: + "object_ptr_kinds h2 = object_ptr_kinds h |\| {|cast new_character_data_ptr|}" + using new_character_data_new_ptr h2 new_character_data_ptr by blast + then have node_ptr_kinds_eq_h: + "node_ptr_kinds h2 = node_ptr_kinds h |\| {|cast new_character_data_ptr|}" + apply(simp add: node_ptr_kinds_def) + by force + then have character_data_ptr_kinds_eq_h: + "character_data_ptr_kinds h2 = character_data_ptr_kinds h |\| {|new_character_data_ptr|}" + apply(simp add: character_data_ptr_kinds_def) + by force + have element_ptr_kinds_eq_h: "element_ptr_kinds h2 = element_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: node_ptr_kinds_def element_ptr_kinds_def) + have document_ptr_kinds_eq_h: "document_ptr_kinds h2 = document_ptr_kinds h" + using object_ptr_kinds_eq_h + by(auto simp add: document_ptr_kinds_def) + + have object_ptr_kinds_eq_h2: "object_ptr_kinds h3 = object_ptr_kinds h2" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_val_writes h3]) + using set_val_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h2: "document_ptr_kinds h3 = document_ptr_kinds h2" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h2: "node_ptr_kinds h3 = node_ptr_kinds h2" + using object_ptr_kinds_eq_h2 + by(auto simp add: node_ptr_kinds_def) + + have object_ptr_kinds_eq_h3: "object_ptr_kinds h' = object_ptr_kinds h3" + apply(rule writes_small_big[where P="\h h'. object_ptr_kinds h' = object_ptr_kinds h", + OF set_disconnected_nodes_writes h']) + using set_disconnected_nodes_pointers_preserved + by (auto simp add: reflp_def transp_def) + then have document_ptr_kinds_eq_h3: "document_ptr_kinds h' = document_ptr_kinds h3" + by (auto simp add: document_ptr_kinds_def) + have node_ptr_kinds_eq_h3: "node_ptr_kinds h' = node_ptr_kinds h3" + using object_ptr_kinds_eq_h3 + by(auto simp add: node_ptr_kinds_def) + + + have "document_ptr |\| document_ptr_kinds h" + using disc_nodes_h3 document_ptr_kinds_eq_h object_ptr_kinds_eq_h2 + get_disconnected_nodes_ptr_in_heap \type_wf h\ document_ptr_kinds_def + by (metis is_OK_returns_result_I) + + have children_eq_h: "\(ptr'::(_) object_ptr) children. ptr' \ cast new_character_data_ptr + \ h \ get_child_nodes ptr' \\<^sub>r children = h2 \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads h2 + get_child_nodes_new_character_data[rotated, OF new_character_data_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have children_eq2_h: "\ptr'. ptr' \ cast new_character_data_ptr + \ |h \ get_child_nodes ptr'|\<^sub>r = |h2 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + + have "h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []" + using new_character_data_ptr h2 new_character_data_ptr_in_heap[OF h2 new_character_data_ptr] + new_character_data_is_character_data_ptr[OF new_character_data_ptr] + new_character_data_no_child_nodes + by blast + have disconnected_nodes_eq_h: + "\doc_ptr disc_nodes. h \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads h2 + get_disconnected_nodes_new_character_data[OF new_character_data_ptr h2] + apply(auto simp add: reads_def reflp_def transp_def preserved_def)[1] + by blast+ + then have disconnected_nodes_eq2_h: + "\doc_ptr. |h \ get_disconnected_nodes doc_ptr|\<^sub>r = |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have children_eq_h2: + "\ptr' children. h2 \ get_child_nodes ptr' \\<^sub>r children = h3 \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads set_val_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_val_get_child_nodes) + then have children_eq2_h2: + "\ptr'. |h2 \ get_child_nodes ptr'|\<^sub>r = |h3 \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h2: + "\doc_ptr disc_nodes. h2 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_val_writes h3 + apply(rule reads_writes_preserved) + by(auto simp add: set_val_get_disconnected_nodes) + then have disconnected_nodes_eq2_h2: + "\doc_ptr. |h2 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have "type_wf h2" + using \type_wf h\ new_character_data_types_preserved h2 by blast + then have "type_wf h3" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_val_writes h3] + using set_val_types_preserved + by(auto simp add: reflp_def transp_def) + then have "type_wf h'" + using writes_small_big[where P="\h h'. type_wf h \ type_wf h'", OF set_disconnected_nodes_writes h'] + using set_disconnected_nodes_types_preserved + by(auto simp add: reflp_def transp_def) + + have children_eq_h3: + "\ptr' children. h3 \ get_child_nodes ptr' \\<^sub>r children = h' \ get_child_nodes ptr' \\<^sub>r children" + using get_child_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_child_nodes) + then have children_eq2_h3: + " \ptr'. |h3 \ get_child_nodes ptr'|\<^sub>r = |h' \ get_child_nodes ptr'|\<^sub>r" + using select_result_eq by force + have disconnected_nodes_eq_h3: "\doc_ptr disc_nodes. document_ptr \ doc_ptr + \ h3 \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes + = h' \ get_disconnected_nodes doc_ptr \\<^sub>r disc_nodes" + using get_disconnected_nodes_reads set_disconnected_nodes_writes h' + apply(rule reads_writes_preserved) + by(auto simp add: set_disconnected_nodes_get_disconnected_nodes_different_pointers) + then have disconnected_nodes_eq2_h3: "\doc_ptr. document_ptr \ doc_ptr + \ |h3 \ get_disconnected_nodes doc_ptr|\<^sub>r = |h' \ get_disconnected_nodes doc_ptr|\<^sub>r" + using select_result_eq by force + + have disc_nodes_document_ptr_h2: "h2 \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" + using disconnected_nodes_eq_h2 disc_nodes_h3 by auto + then have disc_nodes_document_ptr_h: "h \ get_disconnected_nodes document_ptr \\<^sub>r disc_nodes_h3" + using disconnected_nodes_eq_h by auto + then have "cast new_character_data_ptr \ set disc_nodes_h3" + using \heap_is_wellformed h\ using \cast new_character_data_ptr \ set |h \ node_ptr_kinds_M|\<^sub>r\ + a_all_ptrs_in_heap_def heap_is_wellformed_def + using NodeMonad.ptr_kinds_ptr_kinds_M local.heap_is_wellformed_disc_nodes_in_heap by blast + + have "parent_child_rel h = parent_child_rel h'" + proof - + have "parent_child_rel h = parent_child_rel h2" + proof(auto simp add: parent_child_rel_def)[1] + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h2" + by (simp add: object_ptr_kinds_eq_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h" + and 1: "x \ set |h \ get_child_nodes a|\<^sub>r" + then show "x \ set |h2 \ get_child_nodes a|\<^sub>r" + by (metis ObjectMonad.ptr_kinds_ptr_kinds_M + \cast new_character_data_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ children_eq2_h) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "a |\| object_ptr_kinds h" + using object_ptr_kinds_eq_h \h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []\ + by(auto) + next + fix a x + assume 0: "a |\| object_ptr_kinds h2" + and 1: "x \ set |h2 \ get_child_nodes a|\<^sub>r" + then show "x \ set |h \ get_child_nodes a|\<^sub>r" + by (metis (no_types, lifting) \h2 \ get_child_nodes (cast new_character_data_ptr) \\<^sub>r []\ + children_eq2_h empty_iff empty_set image_eqI select_result_I2) + qed + also have "\ = parent_child_rel h3" + by(auto simp add: parent_child_rel_def object_ptr_kinds_eq_h2 children_eq2_h2) + also have "\ = parent_child_rel h'" + by(auto simp add: parent_child_rel_def object_ptr_kinds_eq_h3 children_eq2_h3) + finally show ?thesis + by simp + qed + have root: "h \ get_root_node (cast document_ptr) \\<^sub>r cast document_ptr" + by (simp add: \document_ptr |\| document_ptr_kinds h\ local.get_root_node_not_node_same) + then + have root': "h' \ get_root_node (cast document_ptr) \\<^sub>r cast document_ptr" + by (simp add: \document_ptr |\| document_ptr_kinds h\ document_ptr_kinds_eq_h + local.get_root_node_not_node_same object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3) + + + have "heap_is_wellformed h'" and "known_ptrs h'" + using create_character_data_preserves_wellformedness assms + by blast+ + + have "cast result |\| object_ptr_kinds h" + using \cast new_character_data_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ + by (metis (full_types) ObjectMonad.ptr_kinds_ptr_kinds_M + \h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr\ assms(4) returns_result_eq) + + obtain to where to: "h \ to_tree_order (cast document_ptr) \\<^sub>r to" + by (meson \document_ptr |\| document_ptr_kinds h\ assms(1) assms(2) assms(3) + document_ptr_kinds_commutes is_OK_returns_result_E local.to_tree_order_ok) + then + have "h \ a_get_component (cast document_ptr) \\<^sub>r to" + using root + by(auto simp add: a_get_component_def) + moreover + obtain to' where to': "h' \ to_tree_order (cast document_ptr) \\<^sub>r to'" + by (meson \heap_is_wellformed h'\ \known_ptrs h'\ \type_wf h'\ is_OK_returns_result_E + local.get_root_node_root_in_heap local.to_tree_order_ok root') + then + have "h' \ a_get_component (cast document_ptr) \\<^sub>r to'" + using root' + by(auto simp add: a_get_component_def) + moreover + have "\child. child \ set to \ child \ set to'" + by (metis \heap_is_wellformed h'\ \known_ptrs h'\ \parent_child_rel h = parent_child_rel h'\ + \type_wf h'\ assms(1) assms(2) assms(3) local.to_tree_order_parent_child_rel to to') + ultimately + have "set |h \ local.a_get_component (cast document_ptr)|\<^sub>r = +set |h' \ local.a_get_component (cast document_ptr)|\<^sub>r" + by(auto simp add: a_get_component_def) + + show ?thesis + apply(auto simp add: is_weakly_dom_component_safe_def Let_def)[1] + using assms(2) assms(3) children_eq_h local.get_child_nodes_ok local.get_child_nodes_ptr_in_heap + local.known_ptrs_known_ptr object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3 returns_result_select_result + apply (metis \h2 \ get_child_nodes (cast\<^sub>c\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>_\<^sub>d\<^sub>a\<^sub>t\<^sub>a\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_character_data_ptr) \\<^sub>r []\ + is_OK_returns_result_I) + + apply (metis \h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr\ assms(4) + character_data_ptr_kinds_commutes h2 new_character_data_ptr new_character_data_ptr_in_heap + node_ptr_kinds_eq_h2 node_ptr_kinds_eq_h3 returns_result_eq) + using \h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr\ + \new_character_data_ptr \ set |h \ character_data_ptr_kinds_M|\<^sub>r\ assms(4) returns_result_eq + apply fastforce + using assms(2) assms(3) children_eq_h local.get_child_nodes_ok local.get_child_nodes_ptr_in_heap + local.known_ptrs_known_ptr object_ptr_kinds_eq_h2 object_ptr_kinds_eq_h3 returns_result_select_result + apply (smt ObjectMonad.ptr_kinds_ptr_kinds_M + \cast\<^sub>c\<^sub>h\<^sub>a\<^sub>r\<^sub>a\<^sub>c\<^sub>t\<^sub>e\<^sub>r\<^sub>_\<^sub>d\<^sub>a\<^sub>t\<^sub>a\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_character_data_ptr \ set |h \ object_ptr_kinds_M|\<^sub>r\ + \h \ create_character_data document_ptr text \\<^sub>r new_character_data_ptr\ assms(1) assms(5) + create_character_data_is_weakly_dom_component_safe_step local.get_component_impl select_result_I2) + done +qed +end + +interpretation i_get_component_create_character_data?: l_get_component_create_character_data\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + known_ptr heap_is_wellformed parent_child_rel type_wf known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_element_by_id get_elements_by_class_name get_elements_by_tag_name set_val set_val_locs + get_disconnected_nodes get_disconnected_nodes_locs set_disconnected_nodes set_disconnected_nodes_locs + create_character_data + by(auto simp add: l_get_component_create_character_data\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_create_character_data\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \create\_document\ + +lemma create_document_not_strongly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" and + h' and new_document_ptr where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ create_document \\<^sub>r new_document_ptr \\<^sub>h h'" and + "\ is_strongly_dom_component_safe {} {cast new_document_ptr} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" + let ?P = "create_document" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?document_ptr = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1"]) + by code_simp+ +qed + +locale l_get_component_create_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order + get_parent get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name + + l_create_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M create_document + for known_ptr :: "(_::linorder) object_ptr \ bool" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and type_wf :: "(_) heap \ bool" + and known_ptrs :: "(_) heap \ bool" + and to_tree_order :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_parent :: "(_) node_ptr \ ((_) heap, exception, (_) object_ptr option) prog" + and get_parent_locs :: "((_) heap \ (_) heap \ bool) set" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_component :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and is_strongly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + and is_weakly_dom_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + and get_root_node :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_locs :: "((_) heap \ (_) heap \ bool) set" + and get_ancestors :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_ancestors_locs :: "((_) heap \ (_) heap \ bool) set" + and get_element_by_id :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr option) prog" + and get_elements_by_class_name :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr list) prog" + and get_elements_by_tag_name :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr list) prog" + and create_document :: "((_) heap, exception, (_) document_ptr) prog" +begin + +lemma create_document_is_weakly_component_safe_step: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ create_document \\<^sub>h h'" + assumes "ptr \ cast |h \ create_document|\<^sub>r" + shows "preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr getter) h h'" + using assms + apply(auto simp add: create_document_def)[1] + by (metis assms(4) assms(5) is_OK_returns_heap_I local.create_document_def new_document_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t + select_result_I) + +lemma create_document_is_weakly_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ create_document \\<^sub>r result" + assumes "h \ create_document \\<^sub>h h'" + shows "is_weakly_dom_component_safe {} {cast result} h h'" +proof - + have "object_ptr_kinds h' = object_ptr_kinds h |\| {|cast result|}" + using assms(4) assms(5) local.create_document_def new_document_new_ptr by auto + moreover have "result |\| document_ptr_kinds h" + using assms(4) assms(5) local.create_document_def new_document_ptr_not_in_heap by auto + ultimately show ?thesis + using assms + apply(auto simp add: is_weakly_dom_component_safe_def Let_def local.create_document_def + new_document_ptr_not_in_heap)[1] + by (metis \result |\| document_ptr_kinds h\ document_ptr_kinds_commutes new_document_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t) +qed +end + +interpretation i_get_component_create_document?: l_get_component_create_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + known_ptr heap_is_wellformed parent_child_rel type_wf known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_element_by_id get_elements_by_class_name get_elements_by_tag_name create_document + by(auto simp add: l_get_component_create_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_create_document\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \insert\_before\ + +lemma insert_before_not_strongly_dom_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" and + h' and ptr and child and ref where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ insert_before ptr child ref \\<^sub>h h'" and + "\ is_strongly_dom_component_safe ({ptr, cast child} \ (cast ` set_option ref)) {} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + e1 \ create_element document_ptr ''div''; + e2 \ create_element document_ptr ''div''; + return (e1, e2) + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e1 = "fst |?h0 \ ?P|\<^sub>r" + let ?e2 = "snd |?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and ptr="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e1" and + child="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e2" and ref=None]) + by code_simp+ +qed + + +lemma append_child_not_strongly_dom_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" and + h' and ptr and child where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ append_child ptr child \\<^sub>h h'" and + "\ is_strongly_dom_component_safe {ptr, cast child} {} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + e1 \ create_element document_ptr ''div''; + e2 \ create_element document_ptr ''div''; + return (e1, e2) + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e1 = "fst |?h0 \ ?P|\<^sub>r" + let ?e2 = "snd |?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and ptr="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e1" and child="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e2"]) + by code_simp+ +qed + + +subsection \get\_owner\_document\ + +lemma get_owner_document_not_strongly_dom_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" and + h' and ptr and owner_document where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ get_owner_document ptr \\<^sub>r owner_document \\<^sub>h h'" and + "\ is_strongly_dom_component_safe {ptr} {cast owner_document} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}) heap" + let ?P = "do { + doc \ create_document; + create_element doc ''div'' + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e1 = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and ptr="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e1"]) + by code_simp+ +qed + + +end diff --git a/DOM_Components/ROOT b/DOM_Components/ROOT new file mode 100644 index 0000000..8fb6060 --- /dev/null +++ b/DOM_Components/ROOT @@ -0,0 +1,14 @@ +chapter AFP + +session "DOM_Components" (AFP) = "Shadow_DOM" + + options [timeout = 3600] + directories + counterexample + theories + Core_DOM_Components + Shadow_DOM_Components + fancy_tabs + document_files + "root.tex" + "root.bib" + "fancytabs-normal.jpg" diff --git a/DOM_Components/Shadow_DOM_Components.thy b/DOM_Components/Shadow_DOM_Components.thy new file mode 100644 index 0000000..14d326a --- /dev/null +++ b/DOM_Components/Shadow_DOM_Components.thy @@ -0,0 +1,1564 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +section \Shadow Root Components\ + +theory Shadow_DOM_Components + imports + Shadow_DOM.Shadow_DOM + Core_DOM_Components +begin + +subsection \get\_component\ + +global_interpretation l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_defs get_root_node get_root_node_locs to_tree_order + defines get_component = a_get_component + and is_strongly_dom_component_safe = a_is_strongly_dom_component_safe + and is_weakly_dom_component_safe = a_is_weakly_dom_component_safe + . + +interpretation i_get_component?: l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name + by(auto simp add: l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms_def get_component_def + is_strongly_dom_component_safe_def is_weakly_dom_component_safe_def instances) +declare l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + + +subsection \attach\_shadow\_root\ + +lemma attach_shadow_root_not_strongly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, 'ShadowRoot::{equal,linorder}) heap" and + h' and host and new_shadow_root_ptr where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ attach_shadow_root host m \\<^sub>r new_shadow_root_ptr \\<^sub>h h'" and + "\ is_strongly_dom_component_safe {cast host} {cast new_shadow_root_ptr} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, +'ShadowRoot::{equal,linorder}) heap" + let ?P = "do { + doc \ create_document; + create_element doc ''div'' + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e1 = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and host="?e1"]) + by code_simp+ +qed + +locale l_get_dom_component_attach_shadow_root\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M heap_is_wellformed parent_child_rel type_wf known_ptr known_ptrs to_tree_order + get_parent get_parent_locs get_child_nodes get_child_nodes_locs get_dom_component + is_strongly_component_safe is_weakly_component_safe get_root_node get_root_node_locs get_ancestors + get_ancestors_locs get_disconnected_nodes get_disconnected_nodes_locs get_element_by_id + get_elements_by_class_name get_elements_by_tag_name + + l_attach_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M known_ptr set_shadow_root set_shadow_root_locs set_mode set_mode_locs + attach_shadow_root type_wf get_tag_name get_tag_name_locs get_shadow_root get_shadow_root_locs + + l_set_mode\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_mode set_mode_locs + + l_set_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M type_wf set_shadow_root set_shadow_root_locs + for known_ptr :: "(_::linorder) object_ptr \ bool" + and heap_is_wellformed :: "(_) heap \ bool" + and parent_child_rel :: "(_) heap \ ((_) object_ptr \ (_) object_ptr) set" + and type_wf :: "(_) heap \ bool" + and known_ptrs :: "(_) heap \ bool" + and to_tree_order :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_parent :: "(_) node_ptr \ ((_) heap, exception, (_) object_ptr option) prog" + and get_parent_locs :: "((_) heap \ (_) heap \ bool) set" + and get_child_nodes :: "(_) object_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_child_nodes_locs :: "(_) object_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_dom_component :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_root_node :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr) prog" + and get_root_node_locs :: "((_) heap \ (_) heap \ bool) set" + and get_ancestors :: "(_) object_ptr \ ((_) heap, exception, (_) object_ptr list) prog" + and get_ancestors_locs :: "((_) heap \ (_) heap \ bool) set" + and get_element_by_id :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr option) prog" + and get_elements_by_class_name :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr list) prog" + and get_elements_by_tag_name :: + "(_) object_ptr \ char list \ ((_) heap, exception, (_) element_ptr list) prog" + and set_shadow_root :: + "(_) element_ptr \ (_) shadow_root_ptr option \ ((_) heap, exception, unit) prog" + and set_shadow_root_locs :: "(_) element_ptr \ ((_) heap, exception, unit) prog set" + and set_mode :: "(_) shadow_root_ptr \ shadow_root_mode \ ((_) heap, exception, unit) prog" + and set_mode_locs :: "(_) shadow_root_ptr \ ((_) heap, exception, unit) prog set" + and attach_shadow_root :: + "(_) element_ptr \ shadow_root_mode \ ((_) heap, exception, (_) shadow_root_ptr) prog" + and get_disconnected_nodes :: "(_) document_ptr \ ((_) heap, exception, (_) node_ptr list) prog" + and get_disconnected_nodes_locs :: "(_) document_ptr \ ((_) heap \ (_) heap \ bool) set" + and is_strongly_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + and is_weakly_component_safe :: + "(_) object_ptr set \ (_) object_ptr set \ (_) heap \ (_) heap \ bool" + and get_tag_name :: "(_) element_ptr \ ((_) heap, exception, char list) prog" + and get_tag_name_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" + and get_shadow_root :: "(_) element_ptr \ ((_) heap, exception, (_) shadow_root_ptr option) prog" + and get_shadow_root_locs :: "(_) element_ptr \ ((_) heap \ (_) heap \ bool) set" +begin + +lemma attach_shadow_root_is_weakly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ attach_shadow_root element_ptr shadow_root_mode \\<^sub>h h'" + assumes "ptr \ cast |h \ attach_shadow_root element_ptr shadow_root_mode|\<^sub>r" + assumes "ptr \ set |h \ get_dom_component (cast element_ptr)|\<^sub>r" + shows "preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr getter) h h'" +proof - + obtain h2 h3 new_shadow_root_ptr where + h2: "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>h h2" and + new_shadow_root_ptr: "h \ new\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>R\<^sub>o\<^sub>o\<^sub>t_M \\<^sub>r new_shadow_root_ptr" and + h3: "h2 \ set_mode new_shadow_root_ptr shadow_root_mode \\<^sub>h h3" and + h': "h3 \ set_shadow_root element_ptr (Some new_shadow_root_ptr) \\<^sub>h h'" + using assms(4) + by(auto simp add: attach_shadow_root_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_tag_name_pure, rotated] + bind_returns_heap_E2[rotated, OF get_shadow_root_pure, rotated] + split: if_splits) + have "h \ attach_shadow_root element_ptr shadow_root_mode \\<^sub>r new_shadow_root_ptr" + using new_shadow_root_ptr h2 h3 h' + using assms(4) + by(auto simp add: attach_shadow_root_def intro!: bind_returns_result_I + bind_pure_returns_result_I[OF get_tag_name_pure] bind_pure_returns_result_I[OF get_shadow_root_pure] + elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_tag_name_pure, rotated] + bind_returns_heap_E2[rotated, OF get_shadow_root_pure, rotated] split: if_splits) + have "preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr getter) h h2" + using h2 new_shadow_root_ptr + by (metis (no_types, lifting) + \h \ attach_shadow_root element_ptr shadow_root_mode \\<^sub>r new_shadow_root_ptr\ assms(5) + new_shadow_root_get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t select_result_I2) + + have "ptr \ cast new_shadow_root_ptr" + using \h \ attach_shadow_root element_ptr shadow_root_mode \\<^sub>r new_shadow_root_ptr\ assms(5) + by auto + + have "preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr getter) h2 h3" + using set_mode_writes h3 + apply(rule reads_writes_preserved2) + apply(auto simp add: set_mode_locs_def all_args_def)[1] + using \ptr \ cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r new_shadow_root_ptr\ + by (metis get_M_Mshadow_root_preserved3) + + have "element_ptr |\| element_ptr_kinds h" + using \h \ attach_shadow_root element_ptr shadow_root_mode \\<^sub>r new_shadow_root_ptr\ + attach_shadow_root_element_ptr_in_heap + by blast + have "ptr \ cast element_ptr" + by (metis (no_types, lifting) \element_ptr |\| element_ptr_kinds h\ assms(1) assms(2) assms(3) + assms(6) element_ptr_kinds_commutes is_OK_returns_result_E get_component_ok local.get_dom_component_ptr + node_ptr_kinds_commutes select_result_I2) + + have "preserved (get_M\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t ptr getter) h3 h'" + using set_shadow_root_writes h' + apply(rule reads_writes_preserved2) + apply(auto simp add: set_shadow_root_locs_def all_args_def)[1] + by (metis \ptr \ cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r element_ptr\ get_M_Element_preserved8) + + show ?thesis + using \preserved (get_M ptr getter) h h2\ \preserved (get_M ptr getter) h2 h3\ + \preserved (get_M ptr getter) h3 h'\ + by(auto simp add: preserved_def) +qed +end + +interpretation i_get_dom_component_attach_shadow_root?: l_get_dom_component_attach_shadow_root\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + known_ptr heap_is_wellformed parent_child_rel type_wf known_ptrs to_tree_order get_parent + get_parent_locs get_child_nodes get_child_nodes_locs get_component get_root_node get_root_node_locs + get_ancestors get_ancestors_locs get_element_by_id get_elements_by_class_name get_elements_by_tag_name + set_shadow_root set_shadow_root_locs set_mode set_mode_locs attach_shadow_root get_disconnected_nodes + get_disconnected_nodes_locs is_strongly_dom_component_safe is_weakly_dom_component_safe get_tag_name + get_tag_name_locs get_shadow_root get_shadow_root_locs + by(auto simp add: l_get_dom_component_attach_shadow_root\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_dom_component_attach_shadow_root\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \get\_shadow\_root\ + +lemma get_shadow_root_not_weakly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, 'Shadowroot::{equal,linorder}) heap" and + element_ptr and shadow_root_ptr_opt and h' where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ get_shadow_root element_ptr \\<^sub>r shadow_root_ptr_opt \\<^sub>h h'" and + "\ is_weakly_dom_component_safe {cast element_ptr} (cast ` set_option shadow_root_ptr_opt) h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, +'Shadowroot::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + html \ create_element document_ptr ''html''; + append_child (cast document_ptr) (cast html); + head \ create_element document_ptr ''head''; + append_child (cast html) (cast head); + body \ create_element document_ptr ''body''; + append_child (cast html) (cast body); + e1 \ create_element document_ptr ''div''; + append_child (cast body) (cast e1); + e2 \ create_element document_ptr ''div''; + append_child (cast e1) (cast e2); + s1 \ attach_shadow_root e1 Open; + e3 \ create_element document_ptr ''slot''; + append_child (cast s1) (cast e3); + return e1 + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e1 = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and element_ptr="?e1"]) + by code_simp+ +qed + +locale l_get_shadow_root_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_shadow_root + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_root_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_root_node_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_shadow_root_get_child_nodes +begin +lemma get_shadow_root_is_component_unsafe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + shows "set |h \ get_component (cast host)|\<^sub>r \ set |h \ get_component (cast shadow_root_ptr)|\<^sub>r = {}" +proof - + have "cast host |\| object_ptr_kinds h" + using assms(4) get_shadow_root_ptr_in_heap by auto + then obtain host_c where host_c: "h \ get_component (cast host) \\<^sub>r host_c" + by (meson assms(1) assms(2) assms(3) get_component_ok is_OK_returns_result_E) + obtain host_root where host_root: "h \ get_root_node (cast host) \\<^sub>r host_root" + by (metis (no_types, lifting) bind_returns_heap_E get_component_def host_c is_OK_returns_result_I + pure_def pure_eq_iff) + + have "cast shadow_root_ptr |\| object_ptr_kinds h" + using get_shadow_root_shadow_root_ptr_in_heap assms shadow_root_ptr_kinds_commutes + using document_ptr_kinds_commutes by blast + then obtain shadow_root_ptr_c where shadow_root_ptr_c: + "h \ get_component (cast shadow_root_ptr) \\<^sub>r shadow_root_ptr_c" + by (meson assms(1) assms(2) assms(3) get_component_ok is_OK_returns_result_E) + have "h \ get_root_node (cast shadow_root_ptr) \\<^sub>r cast shadow_root_ptr" + using \cast shadow_root_ptr |\| object_ptr_kinds h\ + by(auto simp add: get_root_node_def get_ancestors_def intro!: bind_pure_returns_result_I + split: option.splits) + + have "host_root \ cast shadow_root_ptr" + proof (rule ccontr, simp) + assume "host_root = cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr" + + have "(cast shadow_root_ptr, host_root) \ (parent_child_rel h)\<^sup>*" + using \host_root = cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr\ by auto + moreover have "(host_root, cast host) \ (parent_child_rel h)\<^sup>*" + using get_root_node_parent_child_rel host_root assms + by blast + moreover have "(cast host, cast shadow_root_ptr) \ (a_host_shadow_root_rel h)" + using assms(4) apply(auto simp add: a_host_shadow_root_rel_def)[1] + by (metis (mono_tags, lifting) get_shadow_root_ptr_in_heap image_eqI is_OK_returns_result_I + mem_Collect_eq prod.simps(2) select_result_I2) + moreover have " acyclic (parent_child_rel h \ local.a_host_shadow_root_rel h)" + using assms(1)[unfolded heap_is_wellformed_def] + by auto + ultimately show False + using local.parent_child_rel_node_ptr + by (metis (no_types, lifting) Un_iff \host_root = cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr\ + acyclic_def in_rtrancl_UnI rtrancl_into_trancl1) + qed + then have "host_c \ shadow_root_ptr_c" + by (metis \h \ get_root_node (cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr) \\<^sub>r cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r +shadow_root_ptr\ assms(1) assms(2) assms(3) get_dom_component_ptr get_component_root_node_same + host_c host_root local.get_root_node_parent_child_rel local.get_root_node_same_no_parent_parent_child_rel + rtranclE shadow_root_ptr_c) + then have "set host_c \ set shadow_root_ptr_c = {}" + using assms get_dom_component_no_overlap Shadow_DOM.a_heap_is_wellformed_def host_c + shadow_root_ptr_c + by blast + then show ?thesis + using host_c shadow_root_ptr_c + by auto +qed +end + +interpretation i_get_shadow_root_component?: l_get_shadow_root_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf get_shadow_root get_shadow_root_locs get_child_nodes get_child_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs get_tag_name get_tag_name_locs known_ptr + heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs + get_disconnected_document get_disconnected_document_locs known_ptrs to_tree_order get_parent + get_parent_locs get_component is_strongly_dom_component_safe is_weakly_dom_component_safe + get_root_node get_root_node_locs get_ancestors get_ancestors_locs get_element_by_id + get_elements_by_class_name get_elements_by_tag_name remove_shadow_root remove_shadow_root_locs + by(auto simp add: l_get_shadow_root_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_shadow_root_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsection \get\_host\ + +lemma get_host_not_weakly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, 'Shadowroot::{equal,linorder}) heap" and + shadow_root_ptr and host and h' where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ get_host shadow_root_ptr \\<^sub>r host \\<^sub>h h'" and + "\ is_weakly_dom_component_safe {cast shadow_root_ptr} {cast host} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, +'Shadowroot::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + html \ create_element document_ptr ''html''; + append_child (cast document_ptr) (cast html); + head \ create_element document_ptr ''head''; + append_child (cast html) (cast head); + body \ create_element document_ptr ''body''; + append_child (cast html) (cast body); + e1 \ create_element document_ptr ''div''; + append_child (cast body) (cast e1); + e2 \ create_element document_ptr ''div''; + append_child (cast e1) (cast e2); + s1 \ attach_shadow_root e1 Open; + e3 \ create_element document_ptr ''slot''; + append_child (cast s1) (cast e3); + return s1 + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?s1 = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and shadow_root_ptr="?s1"]) + by code_simp+ +qed + +locale l_get_host_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_host + + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_shadow_root_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma get_host_is_component_unsafe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_host shadow_root_ptr \\<^sub>r host" + shows "set |h \ get_component (cast host)|\<^sub>r \ set |h \ get_component (cast shadow_root_ptr)|\<^sub>r = {}" +proof - + have "h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + using assms(1) assms(2) assms(4) local.shadow_root_host_dual by blast + then show ?thesis + using assms(1) assms(2) assms(3) local.get_shadow_root_is_component_unsafe by blast +qed +end + +interpretation i_get_host_component?: l_get_host_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + get_child_nodes get_child_nodes_locs get_disconnected_nodes get_disconnected_nodes_locs + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs known_ptr type_wf heap_is_wellformed + parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs get_disconnected_document + get_disconnected_document_locs known_ptrs to_tree_order get_parent get_parent_locs get_component + is_strongly_dom_component_safe is_weakly_dom_component_safe get_root_node get_root_node_locs + get_ancestors get_ancestors_locs get_element_by_id get_elements_by_class_name get_elements_by_tag_name + remove_shadow_root remove_shadow_root_locs + by(auto simp add: l_get_host_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_host_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + + +subsection \get\_root\_node\_si\ + +locale l_get_component_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_root_node_si_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin + +lemma get_root_node_si_is_component_unsafe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_root_node_si ptr' \\<^sub>r root" + shows "set |h \ get_component ptr'|\<^sub>r = set |h \ get_component root|\<^sub>r \ +set |h \ get_component ptr'|\<^sub>r \ set |h \ get_component root|\<^sub>r = {}" +proof - + have "ptr' |\| object_ptr_kinds h" + using get_ancestors_si_ptr_in_heap assms(4) + by(auto simp add: get_root_node_si_def elim!: bind_returns_result_E2) + then + obtain c where "h \ get_component ptr' \\<^sub>r c" + by (meson assms(1) assms(2) assms(3) local.get_component_ok select_result_I) + moreover + have "root |\| object_ptr_kinds h" + using get_ancestors_si_ptr assms(4) + apply(auto simp add: get_root_node_si_def elim!: bind_returns_result_E2)[1] + by (metis (no_types, lifting) assms(1) assms(2) assms(3) empty_iff empty_set + get_ancestors_si_ptrs_in_heap last_in_set) + then + obtain c' where "h \ get_component root \\<^sub>r c'" + by (meson assms(1) assms(2) assms(3) local.get_component_ok select_result_I) + ultimately show ?thesis + by (metis (no_types, lifting) assms(1) assms(2) assms(3) local.get_dom_component_no_overlap + select_result_I2) +qed +end + +interpretation i_get_component_get_root_node_si?: l_get_component_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf known_ptr known_ptrs get_parent get_parent_locs get_child_nodes get_child_nodes_locs + get_host get_host_locs get_ancestors_si get_ancestors_si_locs get_root_node_si get_root_node_si_locs + get_disconnected_nodes get_disconnected_nodes_locs get_shadow_root get_shadow_root_locs get_tag_name + get_tag_name_locs heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_document + get_disconnected_document_locs to_tree_order get_component is_strongly_dom_component_safe + is_weakly_dom_component_safe get_root_node get_root_node_locs get_ancestors get_ancestors_locs + get_element_by_id get_elements_by_class_name get_elements_by_tag_name + by(auto simp add: l_get_component_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_component_get_root_node_si\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + + +subsection \get\_assigned\_nodes\ + +lemma assigned_nodes_not_weakly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, 'Shadowroot::{equal,linorder}) heap" and + node_ptr and nodes and h' where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ assigned_nodes node_ptr \\<^sub>r nodes \\<^sub>h h'" and + "\ is_weakly_dom_component_safe {cast node_ptr} (cast ` set nodes) h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, +'Shadowroot::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + html \ create_element document_ptr ''html''; + append_child (cast document_ptr) (cast html); + head \ create_element document_ptr ''head''; + append_child (cast html) (cast head); + body \ create_element document_ptr ''body''; + append_child (cast html) (cast body); + e1 \ create_element document_ptr ''div''; + append_child (cast body) (cast e1); + e2 \ create_element document_ptr ''div''; + append_child (cast e1) (cast e2); + s1 \ attach_shadow_root e1 Closed; + e3 \ create_element document_ptr ''slot''; + append_child (cast s1) (cast e3); + return e3 + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e3 = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and node_ptr="?e3"]) + by code_simp+ +qed + +lemma get_composed_root_node_not_weakly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, 'Shadowroot::{equal,linorder}) heap" and + ptr and root and h' where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ get_root_node_si ptr \\<^sub>r root \\<^sub>h h'" and + "\ is_weakly_dom_component_safe {ptr} {root} h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, +'Shadowroot::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + html \ create_element document_ptr ''html''; + append_child (cast document_ptr) (cast html); + head \ create_element document_ptr ''head''; + append_child (cast html) (cast head); + body \ create_element document_ptr ''body''; + append_child (cast html) (cast body); + e1 \ create_element document_ptr ''div''; + append_child (cast body) (cast e1); + e2 \ create_element document_ptr ''div''; + append_child (cast e1) (cast e2); + s1 \ attach_shadow_root e1 Closed; + e3 \ create_element document_ptr ''slot''; + append_child (cast s1) (cast e3); + return e3 + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e3 = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and ptr="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e3"]) + by code_simp+ +qed + +lemma assigned_slot_not_weakly_component_safe: + obtains + h :: "('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, 'element_ptr::{equal,linorder}, +'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, 'shadow_root_ptr::{equal,linorder}, +'Object::{equal,linorder}, 'Node::{equal,linorder}, 'Element::{equal,linorder}, +'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, 'Shadowroot::{equal,linorder}) heap" and + node_ptr and slot_opt and h' where + "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" and + "h \ assigned_slot node_ptr \\<^sub>r slot_opt \\<^sub>h h'" and + "\ is_weakly_dom_component_safe {cast node_ptr} (cast ` set_option slot_opt) h h'" +proof - + let ?h0 = "Heap fmempty ::('object_ptr::{equal,linorder}, 'node_ptr::{equal,linorder}, +'element_ptr::{equal,linorder}, 'character_data_ptr::{equal,linorder}, 'document_ptr::{equal,linorder}, +'shadow_root_ptr::{equal,linorder}, 'Object::{equal,linorder}, 'Node::{equal,linorder}, +'Element::{equal,linorder}, 'CharacterData::{equal,linorder}, 'Document::{equal,linorder}, +'Shadowroot::{equal,linorder}) heap" + let ?P = "do { + document_ptr \ create_document; + html \ create_element document_ptr ''html''; + append_child (cast document_ptr) (cast html); + head \ create_element document_ptr ''head''; + append_child (cast html) (cast head); + body \ create_element document_ptr ''body''; + append_child (cast html) (cast body); + e1 \ create_element document_ptr ''div''; + append_child (cast body) (cast e1); + e2 \ create_element document_ptr ''div''; + append_child (cast e1) (cast e2); + s1 \ attach_shadow_root e1 Open; + e3 \ create_element document_ptr ''slot''; + append_child (cast s1) (cast e3); + return e2 + }" + let ?h1 = "|?h0 \ ?P|\<^sub>h" + let ?e2 = "|?h0 \ ?P|\<^sub>r" + + show thesis + apply(rule that[where h="?h1" and node_ptr="cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r ?e2"]) + by code_simp+ +qed + +locale l_assigned_nodes_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_tag_name + + l_get_child_nodes + + l_heap_is_wellformed\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_find_slot\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_assigned_nodes\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_assigned_nodes_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_adopt_node\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_child_wf2 + + l_insert_before_wf + + l_insert_before_wf2 + + l_insert_before\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ _ _ _ _ _ get_ancestors_si get_ancestors_si_locs + + l_append_child\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_append_child_wf\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ get_ancestors_si get_ancestors_si_locs + + l_set_disconnected_nodes_get_tag_name + + l_set_shadow_root_get_child_nodes + + l_set_child_nodes_get_tag_name + + l_get_shadow_root_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_shadow_root\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_remove_shadow_root_get_tag_name + + l_set_disconnected_nodes_get_shadow_root + + l_set_child_nodes_get_shadow_root + + l_remove_shadow_root_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma find_slot_is_component_unsafe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ find_slot open_flag node_ptr \\<^sub>r Some slot" + shows "set |h \ get_component (cast node_ptr)|\<^sub>r \ set |h \ get_component (cast slot)|\<^sub>r = {}" +proof - + obtain host shadow_root_ptr to where + "h \ get_parent node_ptr \\<^sub>r Some (cast host)" and + "h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" and + "h \ to_tree_order (cast shadow_root_ptr) \\<^sub>r to" and + "cast slot \ set to" + using assms(4) + apply(auto simp add: find_slot_def first_in_tree_order_def elim!: bind_returns_result_E2 + map_filter_M_pure_E[where y=slot] + split: option.splits if_splits list.splits intro!: map_filter_M_pure bind_pure_I)[1] + by (metis element_ptr_casts_commute3)+ + + have "node_ptr |\| node_ptr_kinds h" + using assms(4) find_slot_ptr_in_heap by blast + then obtain node_ptr_c where node_ptr_c: "h \ get_component (cast node_ptr) \\<^sub>r node_ptr_c" + using assms(1) assms(2) assms(3) get_component_ok is_OK_returns_result_E + node_ptr_kinds_commutes[symmetric] + by metis + + then have "cast host \ set node_ptr_c" + using \h \ get_parent node_ptr \\<^sub>r Some (cast host)\ get_component_parent_inside assms(1) + assms(2) assms(3) get_dom_component_ptr + by blast + + then have "h \ get_component (cast host) \\<^sub>r node_ptr_c" + using \h \ get_parent node_ptr \\<^sub>r Some (cast host)\ get_component_subset a_heap_is_wellformed_def + assms(1) assms(2) assms(3) node_ptr_c + by blast + + moreover have "slot |\| element_ptr_kinds h" + using assms(4) find_slot_slot_in_heap by blast + then obtain slot_c where slot_c: "h \ get_component (cast slot) \\<^sub>r slot_c" + using a_heap_is_wellformed_def assms(1) assms(2) assms(3) get_component_ok is_OK_returns_result_E + node_ptr_kinds_commutes[symmetric] element_ptr_kinds_commutes[symmetric] + by metis + then have "cast shadow_root_ptr \ set slot_c" + using \h \ to_tree_order (cast shadow_root_ptr) \\<^sub>r to\ \cast slot \ set to\ + get_component_to_tree_order assms(1) assms(2) assms(3) get_dom_component_ptr + by blast + then have "h \ get_component (cast shadow_root_ptr) \\<^sub>r slot_c" + using \h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr\ get_component_subset assms(1) assms(2) + assms(3) slot_c + by blast + + ultimately show ?thesis + using get_shadow_root_is_component_unsafe assms \h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr\ + node_ptr_c slot_c + by fastforce +qed + +lemma assigned_slot_pure: + "pure (assigned_slot node_ptr) h" + apply(auto simp add: assigned_slot_def a_find_slot_def intro!: bind_pure_I split: option.splits)[1] + by(auto simp add: first_in_tree_order_def intro!: bind_pure_I map_filter_M_pure split: list.splits) + +lemma assigned_slot_is_strongly_dom_component_safe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ assigned_slot node_ptr \\<^sub>r slot_opt \\<^sub>h h'" + assumes "\shadow_root_ptr \ fset (shadow_root_ptr_kinds h). h \ get_mode shadow_root_ptr \\<^sub>r Closed" + shows "is_strongly_dom_component_safe {cast node_ptr} (cast ` set_option slot_opt) h h'" +proof - + have "h = h'" + using assms(5) assigned_slot_pure + by (meson assms(4) pure_returns_heap_eq returns_result_heap_def) + obtain parent_opt where parent_opt: "h \ get_parent node_ptr \\<^sub>r parent_opt" + using assms(4) + by (auto simp add: assigned_slot_def a_find_slot_def returns_result_heap_def + elim!: bind_returns_result_E2 split: option.splits split: if_splits) + then + have "slot_opt = None" + proof (induct parent_opt) + case None + then show ?case + using assms(4) + apply(auto simp add: assigned_slot_def a_find_slot_def returns_result_heap_def + elim!: bind_returns_result_E2 split: option.splits split: if_splits)[1] + by (meson option.distinct(1) returns_result_eq)+ + next + case (Some parent) + then show ?case + proof (cases "is_element_ptr_kind parent") + case True + then obtain host where host: "parent = cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host" + by (metis (no_types, lifting) case_optionE element_ptr_casts_commute3 node_ptr_casts_commute) + moreover have "host |\| element_ptr_kinds h" + using Some.prems element_ptr_kinds_commutes host local.get_parent_parent_in_heap + node_ptr_kinds_commutes + by blast + ultimately obtain shadow_root_opt where shadow_root_opt: + "h \ get_shadow_root host \\<^sub>r shadow_root_opt" + using get_shadow_root_ok + by (meson assms(2) is_OK_returns_result_E) + then show ?thesis + proof (induct shadow_root_opt) + case None + then show ?case + using assms(4) + apply(auto dest!: returns_result_eq[OF \h \ get_parent node_ptr \\<^sub>r Some parent\] + simp add: assigned_slot_def a_find_slot_def returns_result_heap_def elim!: bind_returns_result_E2 + split: option.splits split: if_splits)[1] + using host select_result_I2 by fastforce+ + next + case (Some shadow_root_ptr) + have "shadow_root_ptr |\| shadow_root_ptr_kinds h" + using Some.prems assms(1) local.get_shadow_root_shadow_root_ptr_in_heap by blast + then + have "h \ get_mode shadow_root_ptr \\<^sub>r Closed" + using assms by simp + have "\h \ get_mode shadow_root_ptr \\<^sub>r Open" + proof (rule ccontr, simp) + assume "h \ get_mode shadow_root_ptr \\<^sub>r Open" + then have "Open = Closed" + using returns_result_eq \h \ get_mode shadow_root_ptr \\<^sub>r Closed\ + by fastforce + then show False + by simp + qed + then show ?case + using assms(4) Some parent_opt host + by(auto dest!: returns_result_eq[OF \h \ get_parent node_ptr \\<^sub>r Some parent\] + returns_result_eq[OF \h \ get_shadow_root host \\<^sub>r Some shadow_root_ptr\] + simp add: assigned_slot_def a_find_slot_def returns_result_heap_def + elim!: bind_returns_result_E2 split: option.splits split: if_splits) + qed + next + case False + then show ?thesis + using assms(4) + by(auto dest!: returns_result_eq[OF \h \ get_parent node_ptr \\<^sub>r Some parent\] + simp add: assigned_slot_def a_find_slot_def returns_result_heap_def + elim!: bind_returns_result_E2 split: option.splits split: if_splits) + qed + qed + then show ?thesis + using \h = h'\ + by(auto simp add: is_strongly_dom_component_safe_def preserved_def) +qed + +lemma assigned_nodes_is_component_unsafe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ assigned_nodes element_ptr \\<^sub>r nodes" + assumes "node_ptr \ set nodes" + shows "set |h \ get_component (cast element_ptr)|\<^sub>r \ set |h \ get_component (cast node_ptr)|\<^sub>r = {}" +proof - + have "h \ find_slot False node_ptr \\<^sub>r Some element_ptr" + using assms(4) assms(5) + by(auto simp add: assigned_nodes_def elim!: bind_returns_result_E2 + dest!: filter_M_holds_for_result[where x=node_ptr] intro!: bind_pure_I split: if_splits) + then show ?thesis + using assms find_slot_is_component_unsafe + by blast +qed + +lemma flatten_dom_assigned_nodes_become_children: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ flatten_dom \\<^sub>h h'" + assumes "h \ assigned_nodes slot \\<^sub>r nodes" + assumes "nodes \ []" + shows "h' \ get_child_nodes (cast slot) \\<^sub>r nodes" +proof - + obtain tups h2 element_ptrs shadow_root_ptrs where + "h \ element_ptr_kinds_M \\<^sub>r element_ptrs" and + tups: "h \ map_filter_M2 (\element_ptr. do { + tag \ get_tag_name element_ptr; + assigned_nodes \ assigned_nodes element_ptr; + (if tag = ''slot'' \ assigned_nodes \ [] then return (Some (element_ptr, assigned_nodes)) +else return None)}) element_ptrs \\<^sub>r tups" (is "h \ map_filter_M2 ?f element_ptrs \\<^sub>r tups") and + h2: "h \ forall_M (\(slot, assigned_nodes). do { + get_child_nodes (cast slot) \ forall_M remove; + forall_M (append_child (cast slot)) assigned_nodes + }) tups \\<^sub>h h2" and + "h2 \ shadow_root_ptr_kinds_M \\<^sub>r shadow_root_ptrs" and + h': "h2 \ forall_M (\shadow_root_ptr. do { + host \ get_host shadow_root_ptr; + get_child_nodes (cast host) \ forall_M remove; + get_child_nodes (cast shadow_root_ptr) \ forall_M (append_child (cast host)); + remove_shadow_root host + }) shadow_root_ptrs \\<^sub>h h'" + using \h \ flatten_dom \\<^sub>h h'\ + apply(auto simp add: flatten_dom_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF ElementMonad.ptr_kinds_M_pure, rotated] + bind_returns_heap_E2[rotated, OF ShadowRootMonad.ptr_kinds_M_pure, rotated])[1] + apply(drule pure_returns_heap_eq) + by(auto intro!: map_filter_M2_pure bind_pure_I) + + have all_tups_slot: "\slot assigned_nodes. (slot, assigned_nodes) \ set tups \ +h \ get_tag_name slot \\<^sub>r ''slot''" + using tups + apply(induct element_ptrs arbitrary: tups) + by(auto elim!: bind_returns_result_E2 split: if_splits intro!: map_filter_M2_pure bind_pure_I) + + have "distinct element_ptrs" + using \h \ element_ptr_kinds_M \\<^sub>r element_ptrs\ + by auto + then + have "distinct tups" + using tups + apply(induct element_ptrs arbitrary: tups) + by(auto elim!: bind_returns_result_E2 intro!: map_filter_M2_pure bind_pure_I + split: option.splits if_splits intro: map_filter_pure_foo[rotated] ) + + + have "slot \ set element_ptrs" + using assms(5) assigned_nodes_ptr_in_heap \h \ element_ptr_kinds_M \\<^sub>r element_ptrs\ + by auto + then + have "(slot, nodes) \ set tups" + apply(rule map_filter_M2_in_result[OF tups]) + apply(auto intro!: bind_pure_I)[1] + apply(intro bind_pure_returns_result_I) + using assms assigned_nodes_slot_is_slot + by(auto intro!: bind_pure_returns_result_I) + + have "\slot nodes. (slot, nodes) \ set tups \ h \ assigned_nodes slot \\<^sub>r nodes" + using tups + apply(induct element_ptrs arbitrary: tups) + by(auto elim!: bind_returns_result_E2 intro!: map_filter_M2_pure bind_pure_I split: if_splits) + then + have elementwise_eq: "\slot slot' nodes nodes'. (slot, nodes) \ set tups \ +(slot', nodes') \ set tups \ slot = slot' \ nodes = nodes'" + by (meson returns_result_eq) + + have "\slot nodes. (slot, nodes) \ set tups \ distinct nodes" + using \\slot nodes. (slot, nodes) \ set tups \ h \ assigned_nodes slot \\<^sub>r nodes\ + assigned_nodes_distinct + using assms(1) by blast + + have "\slot slot' nodes nodes'. (slot, nodes) \ set tups \ (slot', nodes') \ set tups \ +slot \ slot' \ set nodes \ set nodes' = {}" + using \\slot nodes. (slot, nodes) \ set tups \ h \ assigned_nodes slot \\<^sub>r nodes\ + assigned_nodes_different_ptr assms(1) assms(2) assms(3) by blast + + have "h \ get_tag_name slot \\<^sub>r ''slot''" + using \(slot, nodes) \ set tups\ all_tups_slot by blast + then have "h2 \ get_tag_name slot \\<^sub>r ''slot''" + using h2 + proof(induct tups arbitrary: h, simp) + case (Cons x xs) + obtain xc ha hb slot' nodes' where + "x = (slot', nodes')" and + "h \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot') \\<^sub>r xc" and + ha: "h \ forall_M remove xc \\<^sub>h ha" and + hb: "ha \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot')) nodes' \\<^sub>h hb" and + remainder: "hb \ forall_M (\(slot, assigned_nodes). Heap_Error_Monad.bind +(get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot)) (\x. Heap_Error_Monad.bind (forall_M remove x) +(\_. forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot)) assigned_nodes))) xs \\<^sub>h h2" + using Cons(3) + by (auto elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_child_nodes_pure, rotated] bind_returns_result_E + bind_returns_result_E2[rotated, OF get_child_nodes_pure, rotated] split: prod.splits) + + have "ha \ get_tag_name slot \\<^sub>r ''slot''" + using \h \ get_tag_name slot \\<^sub>r ''slot''\ ha + proof(induct xc arbitrary: h, simp) + case (Cons a yc) + obtain hb1 where + hb1: "h \ remove a \\<^sub>h hb1" and + hba: "hb1 \ forall_M remove yc \\<^sub>h ha" + using Cons + by (auto elim!: bind_returns_heap_E) + have "hb1 \ get_tag_name slot \\<^sub>r ''slot''" + using \h \ get_tag_name slot \\<^sub>r ''slot''\ hb1 + by(auto simp add: remove_child_locs_def set_child_nodes_get_tag_name + set_disconnected_nodes_get_tag_name + dest!: reads_writes_separate_forwards[OF get_tag_name_reads remove_writes]) + then show ?case + using hba Cons(1) by simp + qed + then + have "hb \ get_tag_name slot \\<^sub>r ''slot''" + using hb + proof (induct nodes' arbitrary: ha, simp) + case (Cons a nodes') + obtain ha1 where + ha1: "ha \ append_child (cast slot') a \\<^sub>h ha1" and + hb: "ha1 \ forall_M (append_child (cast slot')) nodes' \\<^sub>h hb" + using Cons + by (auto elim!: bind_returns_heap_E) + have "ha1 \ get_tag_name slot \\<^sub>r ''slot''" + using \ha \ get_tag_name slot \\<^sub>r ''slot''\ ha1 + by(auto simp add: append_child_def insert_before_locs_def adopt_node_locs_def + adopt_node_locs_def remove_child_locs_def set_child_nodes_get_tag_name + set_disconnected_nodes_get_tag_name + dest!: reads_writes_separate_forwards[OF get_tag_name_reads insert_before_writes] + split: if_splits) + then show ?case + using ha1 hb Cons(1) + by simp + qed + then + show ?case + using Cons(1) remainder by simp + qed + + have "h2 \ get_child_nodes (cast slot) \\<^sub>r nodes \ heap_is_wellformed h2 \ type_wf h2 \ known_ptrs h2" + using \(slot, nodes) \ set tups\ + using h2 assms(1) assms(2) assms(3) \distinct tups\ all_tups_slot elementwise_eq + using \\slot slot' assigned_nodes nodes'. (slot, assigned_nodes) \ set tups \ +(slot', nodes') \ set tups \ slot \ slot' \ set assigned_nodes \ set nodes' = {}\ + using \\slot assigned_nodes. (slot, assigned_nodes) \ set tups \ distinct assigned_nodes\ + proof(induct tups arbitrary: h, simp) + case (Cons x xs) + obtain xc ha hb slot' nodes' where + "x = (slot', nodes')" and + "h \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot') \\<^sub>r xc" and + ha: "h \ forall_M remove xc \\<^sub>h ha" and + hb: "ha \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot')) nodes' \\<^sub>h hb" and + remainder: "hb \ forall_M (\(slot, assigned_nodes). Heap_Error_Monad.bind +(get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot)) (\x. Heap_Error_Monad.bind (forall_M remove x) +(\_. forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot)) assigned_nodes))) xs \\<^sub>h h2" + using Cons(3) + by (auto elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_child_nodes_pure, rotated] bind_returns_result_E + bind_returns_result_E2[rotated, OF get_child_nodes_pure, rotated] split: prod.splits) + + have "\slot assigned_nodes. (slot, assigned_nodes) \ set xs \ h \ get_tag_name slot \\<^sub>r ''slot''" + using Cons by auto + + have "heap_is_wellformed ha" and "type_wf ha" and "known_ptrs ha" + using Cons(4) Cons(5) Cons(6) \h \ forall_M remove xc \\<^sub>h ha\ + apply(induct xc arbitrary: h) + apply(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] + simp add: remove_def split: option.splits)[1] + apply(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] + simp add: remove_def split: option.splits)[1] + apply(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] + simp add: remove_def split: option.splits)[1] + apply(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] + simp add: remove_def split: option.splits)[1] + apply (meson local.remove_child_heap_is_wellformed_preserved local.remove_child_preserves_known_ptrs + local.remove_child_preserves_type_wf) + apply(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] + simp add: remove_def split: option.splits)[1] + apply (meson local.remove_child_heap_is_wellformed_preserved local.remove_child_preserves_known_ptrs + local.remove_child_preserves_type_wf) + apply(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] + simp add: remove_def split: option.splits)[1] + using remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs apply metis + done + then + have "heap_is_wellformed hb" and "type_wf hb" and "known_ptrs hb" + using \ha \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot')) nodes' \\<^sub>h hb\ + apply(induct nodes' arbitrary: ha) + apply(auto elim!: bind_returns_heap_E simp add: append_child_def)[1] + apply(auto elim!: bind_returns_heap_E simp add: append_child_def)[1] + apply(auto elim!: bind_returns_heap_E simp add: append_child_def)[1] + apply(auto elim!: bind_returns_heap_E simp add: append_child_def)[1] + apply (metis insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs) + apply(auto elim!: bind_returns_heap_E simp add: append_child_def)[1] + apply (metis insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs) + apply(auto elim!: bind_returns_heap_E simp add: append_child_def)[1] + apply (metis insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs) + done + + { + fix slot assigned_nodes + assume "(slot, assigned_nodes) \ set xs" + then have "h \ get_tag_name slot \\<^sub>r ''slot''" + using \\slot assigned_nodes. (slot, assigned_nodes) \ set xs \ +h \ get_tag_name slot \\<^sub>r ''slot''\ + by auto + then have "ha \ get_tag_name slot \\<^sub>r ''slot''" + using \h \ forall_M remove xc \\<^sub>h ha\ + apply(induct xc arbitrary: h) + by(auto simp add: remove_child_locs_def set_child_nodes_get_tag_name + set_disconnected_nodes_get_tag_name + dest!: reads_writes_separate_forwards[OF get_tag_name_reads remove_writes] + elim!: bind_returns_heap_E) + then have "hb \ get_tag_name slot \\<^sub>r ''slot''" + using \ha \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot')) nodes' \\<^sub>h hb\ + apply(induct nodes' arbitrary: ha) + by(auto simp add: append_child_def insert_before_locs_def adopt_node_locs_def adopt_node_locs_def + remove_child_locs_def set_child_nodes_get_tag_name set_disconnected_nodes_get_tag_name + dest!: reads_writes_separate_forwards[OF get_tag_name_reads insert_before_writes] + elim!: bind_returns_heap_E + split: if_splits) + } note tag_names_same = this + + show ?case + proof(cases "slot' = slot") + case True + then + have "nodes' = nodes" + using Cons.prems(1) Cons.prems(8) \x = (slot', nodes')\ + by (metis list.set_intros(1)) + then + have "(slot, nodes) \ set xs" + using Cons.prems(6) True \x = (slot', nodes')\ by auto + + have "ha \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r []" + using remove_for_all_empty_children Cons.prems(3) Cons.prems(4) Cons.prems(5) True + \h \ forall_M remove xc \\<^sub>h ha\ + using \h \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot') \\<^sub>r xc\ + by blast + then + have "hb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes" + using append_child_for_all_on_no_children[OF \heap_is_wellformed hb\ \type_wf hb\ \known_ptrs hb\] + True \nodes' = nodes\ + using \ha \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot')) nodes' \\<^sub>h hb\ + using \(slot, nodes) \ set tups\ \\slot assigned_nodes. (slot, assigned_nodes) \ set tups \ +distinct assigned_nodes\ \heap_is_wellformed ha\ \known_ptrs ha\ \type_wf ha\ + local.append_child_for_all_on_no_children + by blast + with \heap_is_wellformed hb\ and \type_wf hb\ and \known_ptrs hb\ + show ?thesis + using \(slot, nodes) \ set xs\ remainder + using \\slot slot' assigned_nodes nodes'. (slot, assigned_nodes) \ set (x#xs) \ +(slot', nodes') \ set (x#xs) \ slot = slot' \ assigned_nodes = nodes'\ + using \(slot, nodes) \ set (x # xs)\ + using \\slot slot' assigned_nodes nodes'. (slot, assigned_nodes) \ set (x#xs) \ +(slot', nodes') \ set (x#xs) \ slot \ slot' \ set assigned_nodes \ set nodes' = {}\ + proof(induct xs arbitrary: hb, simp) + case (Cons y ys) + obtain yc hba hbb slot'' nodes'' where + "y = (slot'', nodes'')" and + "hb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot'') \\<^sub>r yc" and + "hb \ forall_M remove yc \\<^sub>h hba" and + "hba \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot'')) nodes'' \\<^sub>h hbb" and + remainder: "hbb \ forall_M (\(slot, assigned_nodes). Heap_Error_Monad.bind +(get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot)) (\x. Heap_Error_Monad.bind (forall_M remove x) +(\_. forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot)) assigned_nodes))) ys \\<^sub>h h2" + using Cons(7) + by (auto elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_child_nodes_pure, rotated] split: prod.splits) + + have "slot \ slot''" + by (metis Cons.prems(5) Cons.prems(7) Cons.prems(8) \y = (slot'', nodes'')\ + list.set_intros(1) list.set_intros(2)) + then have "set nodes \ set nodes'' = {}" + by (metis Cons.prems(8) Cons.prems(9) \y = (slot'', nodes'')\ list.set_intros(1) + list.set_intros(2)) + + have "hba \ get_child_nodes (cast slot) \\<^sub>r nodes \ +heap_is_wellformed hba \ type_wf hba \ known_ptrs hba" + using \hb \ get_child_nodes (cast slot) \\<^sub>r nodes\ + using \hb \ forall_M remove yc \\<^sub>h hba\ + using \hb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot'') \\<^sub>r yc\ + using \heap_is_wellformed hb\ \type_wf hb\ \known_ptrs hb\ + proof(induct yc arbitrary: hb, simp) + case (Cons a yc) + obtain hb1 where + hb1: "hb \ remove a \\<^sub>h hb1" and + hba: "hb1 \ forall_M remove yc \\<^sub>h hba" + using Cons + by (auto elim!: bind_returns_heap_E) + have "hb \ get_parent a \\<^sub>r Some (cast slot'')" + using Cons.prems(3) Cons.prems(4) Cons.prems(5) Cons.prems(6) local.child_parent_dual + by auto + + moreover + have "heap_is_wellformed hb1" and "type_wf hb1" and "known_ptrs hb1" + using \hb \ remove a \\<^sub>h hb1\ + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using \heap_is_wellformed hb\ and \type_wf hb\ and \known_ptrs hb\ + remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs + apply blast + using \heap_is_wellformed hb\ and \type_wf hb\ and \known_ptrs hb\ + remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs + apply blast + using \hb \ remove a \\<^sub>h hb1\ + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using \heap_is_wellformed hb\ and \type_wf hb\ and \known_ptrs hb\ + remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs + apply blast + using \heap_is_wellformed hb\ and \type_wf hb\ and \known_ptrs hb\ + remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs + apply blast + using \hb \ remove a \\<^sub>h hb1\ + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using \heap_is_wellformed hb\ and \type_wf hb\ and \known_ptrs hb\ + remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs + apply blast + using \heap_is_wellformed hb\ and \type_wf hb\ and \known_ptrs hb\ + remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs + apply blast + done + moreover have "hb1 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot'') \\<^sub>r yc" + using \hb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot'') \\<^sub>r a # yc\ hb1 + using remove_removes_child \heap_is_wellformed hb\ \type_wf hb\ \known_ptrs hb\ + by simp + moreover have "hb1 \ get_child_nodes (cast slot) \\<^sub>r nodes" + using Cons(2) hb1 set_child_nodes_get_child_nodes_different_pointers + \hb \ get_parent a \\<^sub>r Some (cast slot'')\ \slot \ slot''\ + apply(auto simp add: remove_child_locs_def elim!: bind_returns_heap_E + dest!: reads_writes_separate_forwards[OF get_child_nodes_reads remove_writes])[1] + by (metis cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject) + ultimately show ?thesis + using \hb1 \ forall_M remove (yc) \\<^sub>h hba\ Cons + by auto + qed + + + then have "hbb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes \ +heap_is_wellformed hbb \ type_wf hbb \ known_ptrs hbb" + using \hba \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot'')) nodes'' \\<^sub>h hbb\ + using \set nodes \ set nodes'' = {}\ + proof(induct nodes'' arbitrary: hba, simp) + case (Cons a nodes'') + then have "hba \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes" and + "heap_is_wellformed hba" and + "type_wf hba" and + "known_ptrs hba" + by auto + obtain hba1 where + hba1: "hba \ append_child (cast slot'') a \\<^sub>h hba1" and + "hba1 \ forall_M (append_child (cast slot'')) nodes'' \\<^sub>h hbb" + using Cons(3) + by (auto elim!: bind_returns_heap_E) + + have "heap_is_wellformed hba1" and "type_wf hba1" and "known_ptrs hba1" + using \hba \ append_child (cast slot'') a \\<^sub>h hba1\ + apply(auto simp add: append_child_def)[1] + using \heap_is_wellformed hba\ and \type_wf hba\ and \known_ptrs hba\ + insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs + apply blast + using \hba \ append_child (cast slot'') a \\<^sub>h hba1\ + apply(auto simp add: append_child_def)[1] + using \heap_is_wellformed hba\ and \type_wf hba\ and \known_ptrs hba\ + insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs + apply blast + using \hba \ append_child (cast slot'') a \\<^sub>h hba1\ + apply(auto simp add: append_child_def)[1] + using \heap_is_wellformed hba\ and \type_wf hba\ and \known_ptrs hba\ + insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs + apply blast + done + + moreover + have "a \ set nodes" + using \set nodes \ set (a # nodes'') = {}\ + by auto + + + moreover + obtain parent_opt where "hba \ get_parent a \\<^sub>r parent_opt" + using insert_before_child_in_heap hba1 get_parent_ok unfolding append_child_def + by (meson Cons.prems(1) is_OK_returns_heap_I is_OK_returns_result_E) + then + have "hba1 \ get_child_nodes (cast slot) \\<^sub>r nodes" + proof (induct parent_opt) + case None + then show ?case + using \hba \ append_child (cast slot'') a \\<^sub>h hba1\ + using \hba \ get_child_nodes (cast slot) \\<^sub>r nodes\ + using \slot \ slot''\ + apply(auto simp add: append_child_def insert_before_locs_def adopt_node_locs_def + adopt_node_locs_def remove_child_locs_def + elim!: reads_writes_separate_forwards[OF get_child_nodes_reads insert_before_writes])[1] + by (metis cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject + set_child_nodes_get_child_nodes_different_pointers) + next + case (Some parent) + have "parent \ cast slot" + apply(rule ccontr, simp) + using Cons(2) + apply - + apply(rule get_parent_child_dual[OF \hba \ get_parent a \\<^sub>r Some parent\]) + apply(auto)[1] + using \a \ set nodes\ returns_result_eq + by fastforce + show ?case + apply(rule reads_writes_separate_forwards) + apply(fact get_child_nodes_reads) + apply(fact insert_before_writes) + apply(fact \hba \ append_child (cast slot'') a \\<^sub>h hba1\[unfolded append_child_def]) + apply(fact \hba \ get_child_nodes (cast slot) \\<^sub>r nodes\) + using \hba \ get_parent a \\<^sub>r Some parent\ \parent \ cast slot\ \slot \ slot''\ + apply(auto simp add: insert_before_locs_def adopt_node_locs_def adopt_node_locs_def + remove_child_locs_def)[1] + apply (simp_all add: set_child_nodes_get_child_nodes_different_pointers + set_disconnected_nodes_get_child_nodes) + by (metis cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject + set_child_nodes_get_child_nodes_different_pointers) + qed + moreover + have "set nodes \ set nodes'' = {}" + using Cons.prems(3) by auto + ultimately show ?case + using Cons.hyps \hba1 \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot'')) nodes'' \\<^sub>h hbb\ + by blast + qed + show ?case + apply(rule Cons(1)) + using \hbb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes \ +heap_is_wellformed hbb \ type_wf hbb \ known_ptrs hbb\ + apply(auto)[1] + using \hbb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes \ +heap_is_wellformed hbb \ type_wf hbb \ known_ptrs hbb\ + apply(auto)[1] + using \hbb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes \ +heap_is_wellformed hbb \ type_wf hbb \ known_ptrs hbb\ + apply(auto)[1] + using \hbb \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes \ +heap_is_wellformed hbb \ type_wf hbb \ known_ptrs hbb\ + apply(auto)[1] + using Cons.prems(5) apply auto[1] + apply (simp add: remainder) + using Cons.prems(7) apply auto[1] + apply (simp add: True \nodes' = nodes\ \x = (slot', nodes')\) + by (metis Cons.prems(9) insert_iff list.simps(15)) + qed + next + case False + then have "nodes' \ nodes" + using Cons.prems(1) Cons.prems(9) \x = (slot', nodes')\ + by (metis assms(6) inf.idem list.set_intros(1) set_empty2) + then + have "(slot, nodes) \ set xs" + using Cons.prems(1) \x = (slot', nodes')\ + by auto + then show ?thesis + using Cons(1)[simplified, OF \(slot, nodes) \ set xs\ remainder + \heap_is_wellformed hb\ \type_wf hb\ \known_ptrs hb\] + using Cons.prems(6) tag_names_same Cons.prems(8) Cons.prems(9) + by (smt Cons.prems(10) distinct.simps(2) list.set_intros(2)) + qed + qed + then + show ?thesis + using h' \h2 \ get_tag_name slot \\<^sub>r ''slot''\ + proof(induct shadow_root_ptrs arbitrary: h2, simp) + case (Cons shadow_root_ptr shadow_root_ptrs) + then have "h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes" and + "heap_is_wellformed h2" and + "type_wf h2" and + "known_ptrs h2" + by auto + obtain host h2a h2b h2c host_children shadow_root_children where + "h2 \ get_host shadow_root_ptr \\<^sub>r host" and + "h2 \ get_child_nodes (cast host) \\<^sub>r host_children" and + h2a: "h2 \ forall_M remove host_children \\<^sub>h h2a" and + "h2a \ get_child_nodes (cast shadow_root_ptr) \\<^sub>r shadow_root_children" and + h2b: "h2a \ forall_M (append_child (cast host)) shadow_root_children \\<^sub>h h2b" and + "h2b \ remove_shadow_root host \\<^sub>h h2c" and + remainder: "h2c \ forall_M(\shadow_root_ptr. Heap_Error_Monad.bind (get_host shadow_root_ptr) + (\host. Heap_Error_Monad.bind (get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host)) + (\x. Heap_Error_Monad.bind (forall_M remove x) + (\_. Heap_Error_Monad.bind (get_child_nodes (cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr)) + (\x. Heap_Error_Monad.bind (forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host)) x) + (\_. remove_shadow_root host)))))) + shadow_root_ptrs + \\<^sub>h h'" + using Cons(3) + by(auto elim!: bind_returns_heap_E bind_returns_heap_E2[rotated, OF get_host_pure, rotated] + bind_returns_heap_E2[rotated, OF get_child_nodes_pure, rotated]) + + + have "h2 \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + using \h2 \ get_host shadow_root_ptr \\<^sub>r host\ shadow_root_host_dual + using \heap_is_wellformed h2\ \type_wf h2\ by blast + then have "h2a \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + using \h2 \ forall_M remove host_children \\<^sub>h h2a\ + apply(induct host_children arbitrary: h2) + by(auto simp add: set_disconnected_nodes_get_shadow_root set_child_nodes_get_shadow_root + remove_child_locs_def elim!: bind_returns_heap_E + dest!: reads_writes_separate_forwards[OF get_shadow_root_reads remove_writes]) + then have "h2b \ get_shadow_root host \\<^sub>r Some shadow_root_ptr" + using \h2a \ forall_M (append_child (cast host)) shadow_root_children \\<^sub>h h2b\ + apply(induct shadow_root_children arbitrary: h2a) + by(auto simp add: set_disconnected_nodes_get_shadow_root set_child_nodes_get_shadow_root + append_child_def insert_before_locs_def adopt_node_locs_def adopt_node_locs_def remove_child_locs_def + elim!: bind_returns_heap_E dest!: reads_writes_separate_forwards[OF get_shadow_root_reads insert_before_writes] + split: if_splits) + + have "host \ slot" + proof (rule ccontr, simp) + assume "host = slot" + show False + using get_host_valid_tag_name[OF \heap_is_wellformed h2\ \type_wf h2\ + \h2 \ get_host shadow_root_ptr \\<^sub>r host\[unfolded \host = slot\] \h2 \ get_tag_name slot \\<^sub>r ''slot''\] + by(simp) + qed + + have "heap_is_wellformed h2a" and "type_wf h2a" and "known_ptrs h2a" + using \heap_is_wellformed h2\ and \type_wf h2\ and \known_ptrs h2\ + \h2 \ forall_M remove host_children \\<^sub>h h2a\ + apply(induct host_children arbitrary: h2) + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs apply metis + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs apply metis + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs apply metis + done + then + have "heap_is_wellformed h2b" and "type_wf h2b" and "known_ptrs h2b" + using \h2a \ forall_M (append_child (cast host)) shadow_root_children \\<^sub>h h2b\ + apply(induct shadow_root_children arbitrary: h2a) + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + using insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs apply metis + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + using insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs apply metis + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + using insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs apply metis + done + then + have "heap_is_wellformed h2c" and "type_wf h2c" and "known_ptrs h2c" + using remove_shadow_root_preserves \h2b \ remove_shadow_root host \\<^sub>h h2c\ + by blast+ + + moreover + have "h2a \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes" + using \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes\ + using \h2 \ forall_M remove host_children \\<^sub>h h2a\ + using \h2 \ get_child_nodes (cast host) \\<^sub>r host_children\ + using \heap_is_wellformed h2\ \type_wf h2\ \known_ptrs h2\ + proof (induct host_children arbitrary: h2, simp) + case (Cons a host_children) + obtain h21 where "h2 \ remove a \\<^sub>h h21" and + "h21 \ forall_M remove host_children \\<^sub>h h2a" + using Cons(3) + by(auto elim!: bind_returns_heap_E) + + have "heap_is_wellformed h21" and "type_wf h21" and "known_ptrs h21" + using \heap_is_wellformed h2\ and \type_wf h2\ and \known_ptrs h2\ \h2 \ remove a \\<^sub>h h21\ + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs apply (metis) + using \heap_is_wellformed h2\ and \type_wf h2\ and \known_ptrs h2\ \h2 \ remove a \\<^sub>h h21\ + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs apply (metis) + using \heap_is_wellformed h2\ and \type_wf h2\ and \known_ptrs h2\ \h2 \ remove a \\<^sub>h h21\ + apply(auto simp add: remove_def elim!: bind_returns_heap_E + bind_returns_heap_E2[rotated, OF get_parent_pure, rotated] split: option.splits)[1] + using remove_child_heap_is_wellformed_preserved remove_child_preserves_type_wf + remove_child_preserves_known_ptrs apply (metis) + done + have "h2 \ get_parent a \\<^sub>r Some (cast host)" + using \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) \\<^sub>r a # host_children\ + using \heap_is_wellformed h2\ \type_wf h2\ \known_ptrs h2\ child_parent_dual + using heap_is_wellformed_def by auto + then have "h21 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes" + using \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes\ \host \ slot\ + using \h2 \ remove a \\<^sub>h h21\ + apply(auto simp add: remove_child_locs_def set_disconnected_nodes_get_child_nodes + dest!: reads_writes_preserved[OF get_child_nodes_reads remove_writes])[1] + by (meson cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject + set_child_nodes_get_child_nodes_different_pointers) + moreover have "h21 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) \\<^sub>r host_children" + using \h2 \ remove a \\<^sub>h h21\ remove_removes_child[OF \heap_is_wellformed h2\ \type_wf h2\ + \known_ptrs h2\ \h2 \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) \\<^sub>r a # host_children\] + by blast + ultimately show ?case + using \heap_is_wellformed h21\ and \type_wf h21\ and \known_ptrs h21\ + \h21 \ forall_M remove host_children \\<^sub>h h2a\ Cons(1) + using Cons.prems(3) Cons.prems(4) Cons.prems(5) Cons.prems(6) heap_is_wellformed_def + \h2 \ remove a \\<^sub>h h21\ remove_removes_child + by blast + qed + + then + have "h2b \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes" + using \h2a \ forall_M (append_child (cast host)) shadow_root_children \\<^sub>h h2b\ + using \h2a \ get_child_nodes (cast shadow_root_ptr) \\<^sub>r shadow_root_children\ + using \heap_is_wellformed h2a\ \type_wf h2a\ \known_ptrs h2a\ + proof(induct shadow_root_children arbitrary: h2a, simp) + case (Cons a shadow_root_children) + obtain h2a1 where "h2a \ append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) a \\<^sub>h h2a1" and + "h2a1 \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host)) (shadow_root_children) \\<^sub>h h2b" + using Cons(3) + by(auto elim!: bind_returns_heap_E) + + have "heap_is_wellformed h2a1" and "type_wf h2a1" and "known_ptrs h2a1" + using \heap_is_wellformed h2a\ and \type_wf h2a\ and \known_ptrs h2a\ + \h2a \ append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) a \\<^sub>h h2a1\ + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + using insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs apply metis + using \heap_is_wellformed h2a\ and \type_wf h2a\ and \known_ptrs h2a\ + \h2a \ append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) a \\<^sub>h h2a1\ + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + using insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs apply metis + using \heap_is_wellformed h2a\ and \type_wf h2a\ and \known_ptrs h2a\ + \h2a \ append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) a \\<^sub>h h2a1\ + apply(auto simp add: append_child_def elim!: bind_returns_heap_E)[1] + using insert_before_heap_is_wellformed_preserved insert_before_preserves_type_wf + insert_before_preserves_known_ptrs apply metis + done + moreover have "h2a1 \ get_child_nodes (cast shadow_root_ptr) \\<^sub>r shadow_root_children" + using \h2a \ get_child_nodes (cast shadow_root_ptr) \\<^sub>r a # shadow_root_children\ + using insert_before_removes_child + \h2a \ append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) a \\<^sub>h h2a1\[unfolded append_child_def] + using \heap_is_wellformed h2a\ \type_wf h2a\ \known_ptrs h2a\ + using cast_document_ptr_not_node_ptr(2) + using cast_shadow_root_ptr_not_node_ptr(2) by blast + moreover have "h2a \ get_parent a \\<^sub>r Some (cast shadow_root_ptr)" + using \h2a \ get_child_nodes (cast\<^sub>s\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>r\<^sub>o\<^sub>o\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r shadow_root_ptr) \\<^sub>r a # shadow_root_children\ + using \heap_is_wellformed h2a\ \type_wf h2a\ \known_ptrs h2a\ child_parent_dual + using heap_is_wellformed_def by auto + then have "h2a1 \ get_child_nodes (cast slot) \\<^sub>r nodes" + using \h2a \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes\ + using \h2a \ append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host) a \\<^sub>h h2a1\ \host \ slot\ + apply(auto simp add: set_disconnected_nodes_get_child_nodes append_child_def + insert_before_locs_def adopt_node_locs_def adopt_node_locs_def remove_child_locs_def + elim!: bind_returns_heap_E dest!: reads_writes_preserved[OF get_child_nodes_reads + insert_before_writes])[1] + using set_child_nodes_get_child_nodes_different_pointers cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject + cast\<^sub>n\<^sub>o\<^sub>d\<^sub>e\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r_inject cast_document_ptr_not_node_ptr(2) + by (metis cast_shadow_root_ptr_not_node_ptr(2))+ + ultimately + show ?case + using Cons(1) \h2a1 \ forall_M (append_child (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r host)) shadow_root_children \\<^sub>h h2b\ + by blast + qed + then + have "h2c \ get_child_nodes (cast\<^sub>e\<^sub>l\<^sub>e\<^sub>m\<^sub>e\<^sub>n\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r\<^sub>2\<^sub>o\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t\<^sub>_\<^sub>p\<^sub>t\<^sub>r slot) \\<^sub>r nodes" + using \h2b \ remove_shadow_root host \\<^sub>h h2c\ + apply(auto simp add: remove_shadow_root_get_child_nodes_different_pointers + dest!: reads_writes_separate_forwards[OF get_child_nodes_reads remove_shadow_root_writes])[1] + by (meson cast_shadow_root_ptr_not_node_ptr(2) + local.remove_shadow_root_get_child_nodes_different_pointers) + + moreover + have "h2a \ get_tag_name slot \\<^sub>r ''slot''" + using h2a \h2 \ get_tag_name slot \\<^sub>r ''slot''\ + apply(induct host_children arbitrary: h2) + by(auto simp add: remove_child_locs_def set_disconnected_nodes_get_tag_name + set_child_nodes_get_tag_name dest!: reads_writes_separate_forwards[OF get_tag_name_reads remove_writes] + elim!: bind_returns_heap_E) + then + have "h2b \ get_tag_name slot \\<^sub>r ''slot''" + using h2b + apply(induct shadow_root_children arbitrary: h2a) + by(auto simp add: append_child_def insert_before_locs_def adopt_node_locs_def adopt_node_locs_def + remove_child_locs_def set_disconnected_nodes_get_tag_name set_child_nodes_get_tag_name + dest!: reads_writes_separate_forwards[OF get_tag_name_reads insert_before_writes] + elim!: bind_returns_heap_E split: if_splits) + then + have "h2c \ get_tag_name slot \\<^sub>r ''slot''" + using \h2b \ remove_shadow_root host \\<^sub>h h2c\ + by(auto simp add: remove_shadow_root_get_tag_name + dest!: reads_writes_separate_forwards[OF get_tag_name_reads remove_shadow_root_writes]) + + ultimately show ?case + using Cons(1) remainder + by auto + qed +qed +end +interpretation i_assigned_nodes_component?: l_assigned_nodes_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf get_tag_name get_tag_name_locs known_ptr get_child_nodes get_child_nodes_locs + get_disconnected_nodes get_disconnected_nodes_locs get_shadow_root get_shadow_root_locs + heap_is_wellformed parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_host get_host_locs + get_disconnected_document get_disconnected_document_locs get_parent get_parent_locs + get_mode get_mode_locs get_attribute get_attribute_locs first_in_tree_order find_slot + assigned_slot known_ptrs to_tree_order assigned_nodes assigned_nodes_flatten flatten_dom + get_root_node get_root_node_locs remove insert_before insert_before_locs append_child + remove_shadow_root remove_shadow_root_locs set_shadow_root set_shadow_root_locs remove_child + remove_child_locs get_component is_strongly_dom_component_safe is_weakly_dom_component_safe + get_ancestors get_ancestors_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name get_owner_document set_disconnected_nodes set_disconnected_nodes_locs + adopt_node adopt_node_locs set_child_nodes set_child_nodes_locs + by(auto simp add: l_assigned_nodes_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_assigned_nodes_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + + +subsubsection \get\_owner\_document\ + +locale l_get_owner_document_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M = + l_get_owner_document_wf\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M +begin +lemma get_owner_document_is_component_unsafe: + assumes "heap_is_wellformed h" and "type_wf h" and "known_ptrs h" + assumes "h \ get_owner_document ptr \\<^sub>r owner_document" + assumes "\is_document_ptr_kind |h \ get_root_node ptr|\<^sub>r" + shows "set |h \ get_component ptr|\<^sub>r \ set |h \ get_component (cast owner_document)|\<^sub>r = {}" +proof - + have "owner_document |\| document_ptr_kinds h" + using assms(1) assms(2) assms(3) assms(4) get_owner_document_owner_document_in_heap by blast + have "ptr |\| object_ptr_kinds h" + by (meson assms(4) is_OK_returns_result_I local.get_owner_document_ptr_in_heap) + obtain root where root: "h \ get_root_node ptr \\<^sub>r root" + by (meson assms(1) assms(2) assms(3) assms(4) is_OK_returns_result_I + local.get_owner_document_ptr_in_heap local.get_root_node_ok returns_result_select_result) + then obtain to where to: "h \ to_tree_order root \\<^sub>r to" + by (meson assms(1) assms(2) assms(3) is_OK_returns_result_E local.get_root_node_root_in_heap + local.to_tree_order_ok) + then have "\p \ set to. \is_document_ptr_kind p" + by (metis (no_types, lifting) assms(1) assms(2) assms(3) assms(5) document_ptr_casts_commute3 + local.to_tree_order_node_ptrs node_ptr_no_document_ptr_cast root select_result_I2) + then have "cast owner_document \ set |h \ get_component ptr|\<^sub>r" + by (metis (no_types, lifting) assms(1) assms(2) assms(3) assms(5) document_ptr_document_ptr_cast + is_OK_returns_result_I l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_component_ok local.get_component_root_node_same + local.get_root_node_not_node_same local.get_root_node_ptr_in_heap local.l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms + node_ptr_no_document_ptr_cast returns_result_select_result root select_result_I2) + then have "|h \ get_component ptr|\<^sub>r \ |h \ get_component (cast owner_document)|\<^sub>r" + by (metis (no_types, lifting) \owner_document |\| document_ptr_kinds h\ assms(1) assms(2) assms(3) + document_ptr_kinds_commutes l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_component_ok local.get_dom_component_ptr + local.l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms returns_result_select_result) + then show ?thesis + by (meson \owner_document |\| document_ptr_kinds h\ \ptr |\| object_ptr_kinds h\ assms(1) + assms(2) assms(3) document_ptr_kinds_commutes l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_dom_component_no_overlap + l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M.get_component_ok local.l_get_component\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms returns_result_select_result) +qed + +end +interpretation i_get_owner_document_component?: l_get_owner_document_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M + type_wf get_disconnected_nodes get_disconnected_nodes_locs known_ptr get_child_nodes + get_child_nodes_locs DocumentClass.known_ptr get_parent get_parent_locs get_root_node_si + get_root_node_si_locs CD.a_get_owner_document get_host get_host_locs get_owner_document + get_shadow_root get_shadow_root_locs get_tag_name get_tag_name_locs heap_is_wellformed + parent_child_rel heap_is_wellformed\<^sub>C\<^sub>o\<^sub>r\<^sub>e\<^sub>_\<^sub>D\<^sub>O\<^sub>M get_disconnected_document get_disconnected_document_locs + known_ptrs get_ancestors_si get_ancestors_si_locs to_tree_order get_component + is_strongly_dom_component_safe is_weakly_dom_component_safe get_root_node get_root_node_locs + get_ancestors get_ancestors_locs get_element_by_id get_elements_by_class_name + get_elements_by_tag_name + by(auto simp add: l_get_owner_document_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_def instances) +declare l_get_owner_document_component\<^sub>S\<^sub>h\<^sub>a\<^sub>d\<^sub>o\<^sub>w\<^sub>_\<^sub>D\<^sub>O\<^sub>M_axioms [instances] + +definition is_shadow_root_component :: "(_) object_ptr list \ bool" + where + "is_shadow_root_component c = is_shadow_root_ptr_kind (hd c)" + +end diff --git a/DOM_Components/counterexample/fancy-tabs.html b/DOM_Components/counterexample/fancy-tabs.html new file mode 100644 index 0000000..1a17eaf --- /dev/null +++ b/DOM_Components/counterexample/fancy-tabs.html @@ -0,0 +1,40 @@ + + + + Global News + + + +

Global News

+ + +
+
+ + + + + + + +
content panel 1
+
    +
  • News Item 1
  • +
  • News Item 2
  • +
  • News Item 3
  • +
+
content panel 3
+
+ + + diff --git a/DOM_Components/counterexample/fancy_tabs.thy b/DOM_Components/counterexample/fancy_tabs.thy new file mode 100644 index 0000000..f9d0097 --- /dev/null +++ b/DOM_Components/counterexample/fancy_tabs.thy @@ -0,0 +1,96 @@ +(*********************************************************************************** + * Copyright (c) 2016-2020 The University of Sheffield, UK + * 2019-2020 University of Exeter, UK + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause + ***********************************************************************************) + +(* This file is automatically generated, please do not modify! *) + +section\Testing fancy\_tabs\ +text\This theory contains the test cases for fancy\_tabs.\ + +theory fancy_tabs +imports + "Shadow_DOM.Shadow_DOM" +begin + +definition fancy_tabs_heap :: "heap\<^sub>f\<^sub>i\<^sub>n\<^sub>a\<^sub>l" where + "fancy_tabs_heap = create_heap [(cast (document_ptr.Ref 1), cast (create_document_obj html (Some (cast (element_ptr.Ref 1))) [])), + (cast (element_ptr.Ref 1), cast (create_element_obj ''html'' [cast (element_ptr.Ref 2), cast (element_ptr.Ref 4)] fmempty None)), + (cast (element_ptr.Ref 2), cast (create_element_obj ''head'' [cast (element_ptr.Ref 3)] fmempty None)), + (cast (element_ptr.Ref 3), cast (create_element_obj ''title'' [cast (character_data_ptr.Ref 1)] fmempty None)), + (cast (character_data_ptr.Ref 1), cast (create_character_data_obj ''Global%20News'')), + (cast (element_ptr.Ref 4), cast (create_element_obj ''body'' [cast (element_ptr.Ref 5), cast (element_ptr.Ref 6), cast (element_ptr.Ref 7), cast (element_ptr.Ref 8), cast (element_ptr.Ref 9), cast (element_ptr.Ref 10), cast (element_ptr.Ref 30)] fmempty None)), + (cast (element_ptr.Ref 5), cast (create_element_obj ''h1'' [cast (character_data_ptr.Ref 2)] fmempty None)), + (cast (character_data_ptr.Ref 2), cast (create_character_data_obj ''Global%20News'')), + (cast (element_ptr.Ref 6), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 3)] fmempty None)), + (cast (character_data_ptr.Ref 3), cast (create_character_data_obj ''Search'')), + (cast (element_ptr.Ref 7), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 4)] fmempty None)), + (cast (character_data_ptr.Ref 4), cast (create_character_data_obj ''Sign%20In'')), + (cast (element_ptr.Ref 8), cast (create_element_obj ''br'' [] fmempty None)), + (cast (element_ptr.Ref 9), cast (create_element_obj ''br'' [] fmempty None)), + (cast (element_ptr.Ref 10), cast (create_element_obj ''fancy-tabs'' [cast (element_ptr.Ref 11), cast (element_ptr.Ref 12), cast (element_ptr.Ref 13), cast (element_ptr.Ref 14), cast (element_ptr.Ref 15), cast (element_ptr.Ref 22)] (fmap_of_list [(''background'', '''')]) (Some (cast (shadow_root_ptr.Ref 1))))), + (cast (element_ptr.Ref 11), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 5)] (fmap_of_list [(''slot'', ''title'')]) None)), + (cast (character_data_ptr.Ref 5), cast (create_character_data_obj ''Politics'')), + (cast (element_ptr.Ref 12), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 6)] (fmap_of_list [(''slot'', ''title''), (''selected'', '''')]) None)), + (cast (character_data_ptr.Ref 6), cast (create_character_data_obj ''Sports'')), + (cast (element_ptr.Ref 13), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 7)] (fmap_of_list [(''slot'', ''title'')]) None)), + (cast (character_data_ptr.Ref 7), cast (create_character_data_obj ''Culture'')), + (cast (element_ptr.Ref 14), cast (create_element_obj ''section'' [cast (character_data_ptr.Ref 8)] fmempty None)), + (cast (character_data_ptr.Ref 8), cast (create_character_data_obj ''content%20panel%201'')), + (cast (element_ptr.Ref 15), cast (create_element_obj ''ul'' [cast (element_ptr.Ref 16), cast (element_ptr.Ref 18), cast (element_ptr.Ref 20)] fmempty None)), + (cast (element_ptr.Ref 16), cast (create_element_obj ''li'' [cast (character_data_ptr.Ref 9), cast (element_ptr.Ref 17)] fmempty None)), + (cast (character_data_ptr.Ref 9), cast (create_character_data_obj ''News%20Item%201'')), + (cast (element_ptr.Ref 17), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 10)] fmempty None)), + (cast (character_data_ptr.Ref 10), cast (create_character_data_obj ''Share'')), + (cast (element_ptr.Ref 18), cast (create_element_obj ''li'' [cast (character_data_ptr.Ref 11), cast (element_ptr.Ref 19)] fmempty None)), + (cast (character_data_ptr.Ref 11), cast (create_character_data_obj ''News%20Item%202'')), + (cast (element_ptr.Ref 19), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 12)] fmempty None)), + (cast (character_data_ptr.Ref 12), cast (create_character_data_obj ''Share'')), + (cast (element_ptr.Ref 20), cast (create_element_obj ''li'' [cast (character_data_ptr.Ref 13), cast (element_ptr.Ref 21)] fmempty None)), + (cast (character_data_ptr.Ref 13), cast (create_character_data_obj ''News%20Item%203'')), + (cast (element_ptr.Ref 21), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 14)] fmempty None)), + (cast (character_data_ptr.Ref 14), cast (create_character_data_obj ''Share'')), + (cast (element_ptr.Ref 22), cast (create_element_obj ''section'' [cast (character_data_ptr.Ref 15)] fmempty None)), + (cast (character_data_ptr.Ref 15), cast (create_character_data_obj ''content%20panel%203'')), + (cast (shadow_root_ptr.Ref 1), cast (create_shadow_root_obj Open [cast (element_ptr.Ref 23), cast (element_ptr.Ref 24), cast (element_ptr.Ref 26), cast (element_ptr.Ref 28), cast (element_ptr.Ref 29)])), + (cast (element_ptr.Ref 23), cast (create_element_obj ''style'' [cast (character_data_ptr.Ref 16)] fmempty None)), + (cast (character_data_ptr.Ref 16), cast (create_character_data_obj ''---shortened---'')), + (cast (element_ptr.Ref 24), cast (create_element_obj ''div'' [cast (element_ptr.Ref 25)] (fmap_of_list [(''id'', ''tabs'')]) None)), + (cast (element_ptr.Ref 25), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''tabsSlot''), (''name'', ''title'')]) None)), + (cast (element_ptr.Ref 26), cast (create_element_obj ''div'' [cast (element_ptr.Ref 27)] (fmap_of_list [(''id'', ''panels'')]) None)), + (cast (element_ptr.Ref 27), cast (create_element_obj ''slot'' [] (fmap_of_list [(''id'', ''panelsSlot'')]) None)), + (cast (element_ptr.Ref 28), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 17)] fmempty None)), + (cast (character_data_ptr.Ref 17), cast (create_character_data_obj ''Previous%20Tab'')), + (cast (element_ptr.Ref 29), cast (create_element_obj ''button'' [cast (character_data_ptr.Ref 18)] (fmap_of_list [(''style'', ''float:right'')]) None)), + (cast (character_data_ptr.Ref 18), cast (create_character_data_obj ''Next%20Tab'')), + (cast (element_ptr.Ref 30), cast (create_element_obj ''script'' [] fmempty None))]" + +definition fancy_tabs_document :: "(unit, unit, unit, unit, unit, unit) object_ptr option" where "fancy_tabs_document = Some (cast (document_ptr.Ref 1))" + + +end diff --git a/DOM_Components/document/fancytabs-normal.jpg b/DOM_Components/document/fancytabs-normal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ffe62d666c8862ebadf014eff01173d5cb182b3c GIT binary patch literal 34081 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 literal 0 HcmV?d00001 diff --git a/DOM_Components/document/root.bib b/DOM_Components/document/root.bib new file mode 100644 index 0000000..710eec2 --- /dev/null +++ b/DOM_Components/document/root.bib @@ -0,0 +1,747 @@ +@STRING{j-fac = "Formal Aspects of Computing" } +@STRING{pub-springer={Springer-Verlag} } +@STRING{pub-springer:adr={Heidelberg} } +@STRING{s-lncs = "Lecture Notes in Computer Science" } + +@Book{ nipkow.ea:isabelle:2002, + author = {Tobias Nipkow and Lawrence C. Paulson and Markus Wenzel}, + title = {Isabelle/HOL---A Proof Assistant for Higher-Order Logic}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + volume = 2283, + doi = {10.1007/3-540-45949-9}, + abstract = {This book is a self-contained introduction to interactive + proof in higher-order logic (HOL), using the proof + assistant Isabelle2002. It is a tutorial for potential + users rather than a monograph for researchers. The book has + three parts. + + 1. Elementary Techniques shows how to model functional + programs in higher-order logic. Early examples involve + lists and the natural numbers. Most proofs are two steps + long, consisting of induction on a chosen variable followed + by the auto tactic. But even this elementary part covers + such advanced topics as nested and mutual recursion. 2. + Logic and Sets presents a collection of lower-level tactics + that you can use to apply rules selectively. It also + describes Isabelle/HOL's treatment of sets, functions and + relations and explains how to define sets inductively. One + of the examples concerns the theory of model checking, and + another is drawn from a classic textbook on formal + languages. 3. Advanced Material describes a variety of + other topics. Among these are the real numbers, records and + overloading. Advanced techniques are described involving + induction and recursion. A whole chapter is devoted to an + extended example: the verification of a security protocol. + }, + year = 2002, + acknowledgement={brucker, 2007-02-19}, + bibkey = {nipkow.ea:isabelle:2002} +} + +@Misc{ dom-specification, + year = 2016, + month = {DOM Living Standard -- Last Updated 20 October 2016}, + day = 20, + url = {https://dom.spec.whatwg.org/}, + organization = {Web Hypertext Application Technology Working Group + (WHATWG)}, + note = {An archived copy of the version from 20 October 2016 is + available at + \url{https://git.logicalhacking.com/BrowserSecurity/fDOM-idl/}.} +} + +@InProceedings{ brucker.ea:core-dom:2018, + author = {Achim D. Brucker and Michael Herzberg}, + title = {A Formal Semantics of the Core {DOM} in {Isabelle/HOL}}, + booktitle = {Proceedings of the Web Programming, Design, Analysis, And + Implementation (WPDAI) track at WWW 2018}, + location = {Lyon, France}, + url = {https://www.brucker.ch/bibliography/abstract/brucker.ea-fdom-2018}, + year = {2018}, + abstract = {At its core, the Document Object Model (DOM) defines a + tree-like data structure for representing documents in + general and HTML documents in particular. It forms the + heart of any rendering engine of modern web browsers. + Formalizing the key concepts of the DOM is a pre-requisite + for the formal reasoning over client-side JavaScript + programs as well as for the analysis of security concepts + in modern web browsers. In this paper, we present a + formalization of the core DOM, with focus on the node-tree + and the operations defined on node-trees, in Isabelle/HOL. + We use the formalization to verify the functional + correctness of the most important functions defined in the + DOM standard. Moreover, our formalization is (1) + extensible, i.e., can be extended without the need of + re-proving already proven properties and (2) executable, + i.e., we can generate executable code from our + specification. }, + keywords = {Document Object Model, DOM, Formal Semantics, + Isabelle/HOL}, + classification= {conference}, + areas = {formal methods, software}, + public = {yes} +} +@Article{ klein:operating:2009, + author = {Gerwin Klein}, + title = {Operating System Verification --- An Overview}, + journal = {S\={a}dhan\={a}}, + publisher = pub-springer, + year = 2009, + volume = 34, + number = 1, + month = feb, + pages = {27--69}, + abstract = {This paper gives a high-level introduction to the topic of + formal, interactive, machine-checked software verification + in general, and the verification of operating systems code + in particular. We survey the state of the art, the + advantages and limitations of machine-checked code proofs, + and describe two specific ongoing larger-scale verification + projects in more detail.} +} + + +@InProceedings{ gardner.ea:securing:2009, + author = {Ryan W. Gardner and Sujata Garera and Matthew W. Pagano + and Matthew Green and Aviel D. Rubin}, + title = {Securing medical records on smart phones}, + booktitle = {ACM workshop on Security and privacy in medical and + home-care systems (SPIMACS)}, + year = 2009, + isbn = {978-1-60558-790-5}, + pages = {31--40}, + location = {Chicago, Illinois, USA}, + doi = {10.1145/1655084.1655090}, + address = pub-acm:adr, + publisher = pub-acm, + abstract = {There is an inherent conflict between the desire to + maintain privacy of one's medical records and the need to + make those records available during an emergency. To + satisfy both objectives, we introduce a flexible + architecture for the secure storage of medical records on + smart phones. In our system, a person can view her records + at any time, and emergency medical personnel can view the + records as long as the person is present (even if she is + unconscious). Our solution allows for efficient revocation + of access rights and is robust against adversaries who can + access the phone's storage offline.} +} + +@InProceedings{ raad.ea:dom:2016, + author = {Azalea Raad and Jos{\'{e}} Fragoso Santos and Philippa + Gardner}, + title = {{DOM:} Specification and Client Reasoning}, + booktitle = {Programming Languages and Systems - 14th Asian Symposium, + {APLAS} 2016, Hanoi, Vietnam, November 21-23, 2016, + Proceedings}, + pages = {401--422}, + year = 2016, + crossref = {igarashi:programming:2016}, + doi = {10.1007/978-3-319-47958-3_21}, + abstract = {We present an axiomatic specification of a key fragment of + DOM using structural separation logic. This specification + allows us to develop modular reasoning about client + programs that call the DOM.} +} + + +@InProceedings{ bohannon.ea:featherweight:2010, + author = {Aaron Bohannon and Benjamin C. Pierce}, + title = {Featherweight {F}irefox: {F}ormalizing the Core of a Web + Browser}, + booktitle = {Usenix Conference on Web Application Development + (WebApps)}, + year = 2010, + month = jun, + url = {http://www.cis.upenn.edu/~bohannon/browser-model/}, + abstract = {We offer a formal specification of the core functionality + of a web browser in the form of a small-step operational + semantics. The specification accurately models the asyn- + chronous nature of web browsers and covers the basic as- + pects of windows, DOM trees, cookies, HTTP requests and + responses, user input, and a minimal scripting lan- guage + with first-class functions, dynamic evaluation, and AJAX + requests. No security enforcement mechanisms are + included{\^a}instead, the model is intended to serve as a + basis for formalizing and experimenting with different + security policies and mechanisms. We survey the most + interesting design choices and discuss how our model re- + lates to real web browsers.} +} + +@Proceedings{ joyce.ea:higher:1994, + editor = {Jeffrey J. Joyce and Carl-Johan H. Seger}, + title = {Higher Order Logic Theorem Proving and Its Applications + (HUG)}, + booktitle = {Higher Order Logic Theorem Proving and Its Applications + (HUG)}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + abstract = {Theorem proving based techniques for formal hardware + verification have been evolving constantly and researchers + are getting able to reason about more complex issues than + it was possible or practically feasible in the past. It is + often the case that a model of a system is built in a + formal logic and then reasoning about this model is carried + out in the logic. Concern is growing on how to consistently + interface a model built in a formal logic with an informal + CAD environment. Researchers have been investigating how to + define the formal semantics of hardware description + languages so that one can formally reason about models + informally dealt with in a CAD environment. At the + University of Cambridge, the embedding of hardware + description languages in a logic is classified in two + categories: deep embedding and shallow embedding. In this + paper we argue that there are degrees of formality in + shallow embedding a language in a logic. The choice of the + degree of formality is a trade-off between the security of + the embedding and the amount and complexity of the proof + effort in the logic. We also argue that the design of a + language could consider this verifiability issue. There are + choices in the design of a language that can make it easier + to improve the degree of formality, without implying + serious drawbacks for the CAD environment.}, + volume = 780, + year = 1994, + doi = {10.1007/3-540-57826-9}, + isbn = {3-540-57826-9}, + acknowledgement={brucker, 2007-02-19} +} + + +@Misc{ whatwg:dom:2017, + key={whatwg}, + author={{WHATWG}}, + url={https://dom.spec.whatwg.org/commit-snapshots/6253e53af2fbfaa6d25ad09fd54280d8083b2a97/}, + month=mar, + year=2017, + day=24, + title={{DOM} -- Living Standard}, + note={Last Updated 24 {March} 2017}, + institution = {WHATWG}, +} + +@Misc{ whatwg:html:2017, + key={whatwg}, + author={{WHATWG}}, + url={https://html.spec.whatwg.org/}, + month=apr, + year=2017, + day=13, + title={{HTML} -- Living Standard}, + note={Last Updated 13 {April} 2017}, + institution = {WHATWG}, +} + + +@Misc{ w3c:dom:2015, + key={w3c}, + author={{W3C}}, + url={https://www.w3.org/TR/dom/}, + month=nov, + year=2015, + day=19, + title={{W3C} {DOM4}}, + institution = {W3C}, +} + + +@Proceedings{ igarashi:programming:2016, + editor = {Atsushi Igarashi}, + title = {Programming Languages and Systems - 14th Asian Symposium, + {APLAS} 2016, Hanoi, Vietnam, November 21-23, 2016, + Proceedings}, + series = {Lecture Notes in Computer Science}, + volume = 10017, + year = 2016, + doi = {10.1007/978-3-319-47958-3}, + isbn = {978-3-319-47957-6} +} + + + + + + +@InProceedings{ gardner.ea:dom:2008, + author = {Philippa Gardner and Gareth Smith and Mark J. Wheelhouse + and Uri Zarfaty}, + title = {{DOM:} Towards a Formal Specification}, + booktitle = {{PLAN-X} 2008, Programming Language Technologies for XML, + An {ACM} {SIGPLAN} Workshop colocated with {POPL} 2008, San + Francisco, California, USA, January 9, 2008}, + year = 2008, + crossref = {plan-x:2008}, + url = {http://gemo.futurs.inria.fr/events/PLANX2008/papers/p18.pdf}, + abstract = {The W3C Document Object Model (DOM) specifies an XML up- + date library. DOM is written in English, and is therefore + not compo- sitional and not complete. We provide a first + step towards a compo- sitional specification of DOM. Unlike + DOM, we are able to work with a minimal set of commands and + obtain a complete reason- ing for straight-line code. Our + work transfers O{\^a}Hearn, Reynolds and Yang{\^a}s + local Hoare reasoning for analysing heaps to XML, viewing + XML as an in-place memory store as does DOM. In par- + ticular, we apply recent work by Calcagno, Gardner and + Zarfaty on local Hoare reasoning about a simple tree-update + language to DOM, showing that our reasoning scales to DOM. + Our reasoning not only formally specifies a significant + subset of DOM Core Level 1, but can also be used to verify + e.g. invariant properties of simple Javascript programs.} +} + + + +@InProceedings{ jang.ea:establishing:2012, + author = {Dongseok Jang and Zachary Tatlock and Sorin Lerner}, + title = {Establishing Browser Security Guarantees through Formal + Shim Verification}, + booktitle = {Proceedings of the 21th {USENIX} Security Symposium, + Bellevue, WA, USA, August 8-10, 2012}, + pages = {113--128}, + year = 2012, + crossref = {kohno:proceedings:2012}, + url = {https://www.usenix.org/conference/usenixsecurity12/technical-sessions/presentation/jang}, + abstract = { Web browsers mediate access to valuable private data in + domains ranging from health care to banking. Despite this + critical role, attackers routinely exploit browser + vulnerabilities to exfiltrate private data and take over + the un- derlying system. We present Q UARK , a browser + whose kernel has been implemented and verified in Coq. We + give a specification of our kernel, show that the + implementation satisfies the specification, and finally + show that the specification implies several security + properties, including tab non-interference, cookie + integrity and confidentiality, and address bar integrity. + } +} + +@Proceedings{ kohno:proceedings:2012, + editor = {Tadayoshi Kohno}, + title = {Proceedings of the 21th {USENIX} Security Symposium, + Bellevue, WA, USA, August 8-10, 2012}, + publisher = {{USENIX} Association}, + year = 2012, + timestamp = {Thu, 15 May 2014 09:12:27 +0200} +} + + + +@Proceedings{ plan-x:2008, + title = {{PLAN-X} 2008, Programming Language Technologies for XML, + An {ACM} {SIGPLAN} Workshop colocated with {POPL} 2008, San + Francisco, California, USA, January 9, 2008}, + year = 2008, + timestamp = {Fri, 18 Jan 2008 13:01:04 +0100} +} + + +@Article{ brucker.ea:extensible:2008-b, + abstract = {We present an extensible encoding of object-oriented data models into HOL. Our encoding is supported by a datatype package that leverages the use of the shallow embedding technique to object-oriented specification and programming languages. The package incrementally compiles an object-oriented data model, i.e., a class model, to a theory containing object-universes, constructors, accessor functions, coercions (casts) between dynamic and static types, characteristic sets, and co-inductive class invariants. The package is conservative, i.e., all properties are derived entirely from constant definitions, including the constraints over object structures. As an application, we use the package for an object-oriented core-language called IMP++, for which we formally prove the correctness of a Hoare-Logic with respect to a denotational semantics.}, + address = {Heidelberg}, + author = {Achim D. Brucker and Burkhart Wolff}, + doi = {10.1007/s10817-008-9108-3}, + issn = {0168-7433}, + issue = {3}, + journal = {Journal of Automated Reasoning}, + keywords = {object-oriented data models, HOL, theorem proving, verification}, + language = {USenglish}, + pages = {219--249}, + pdf = {https://www.brucker.ch/bibliography/download/2008/brucker.ea-extensible-2008-b.pdf}, + publisher = {Springer-Verlag}, + title = {An Extensible Encoding of Object-oriented Data Models in HOL}, + url = {https://www.brucker.ch/bibliography/abstract/brucker.ea-extensible-2008-b}, + volume = {41}, + year = {2008}, +} + +@PhDThesis{ brucker:interactive:2007, + abstract = {We present a semantic framework for object-oriented specification languages. We develop this framework as a conservative shallow embedding in Isabelle/HOL. Using only conservative extensions guarantees by construction the consistency of our formalization. Moreover, we show how our framework can be used to build an interactive proof environment, called HOL-OCL, for object-oriented specifications in general and for UML/OCL in particular.\\\\Our main contributions are an extensible encoding of object-oriented data structures in HOL, a datatype package for object-oriented specifications, and the development of several equational and tableaux calculi for object-oriented specifications. Further, we show that our formal framework can be the basis of a formal machine-checked semantics for OCL that is compliant to the OCL 2.0 standard.}, + abstract_de = {In dieser Arbeit wird ein semantisches Rahmenwerk f{\"u}r objektorientierte Spezifikationen vorgestellt. Das Rahmenwerk ist als konservative, flache Einbettung in Isabelle/HOL realisiert. Durch die Beschr{\"a}nkung auf konservative Erweiterungen kann die logische Konsistenz der Einbettung garantiert werden. Das semantische Rahmenwerk wird verwendet, um das interaktives Beweissystem HOL-OCL f{\"u}r objektorientierte Spezifikationen im Allgemeinen und insbesondere f{\"u}r UML/OCL zu entwickeln.\\\\Die Hauptbeitr{\"a}ge dieser Arbeit sind die Entwicklung einer erweiterbaren Kodierung objektorientierter Datenstrukturen in HOL, ein Datentyp-Paket f{\"u}r objektorientierte Spezifikationen und die Entwicklung verschiedener Kalk{\"u}le f{\"u}r objektorientierte Spezifikationen. Zudem zeigen wir, wie das formale Rahmenwerk verwendet werden kann, um eine formale, maschinell gepr{\"u}fte Semantik f{\"u}r OCL anzugeben, die konform zum Standard f{\"u}r OCL 2.0 ist.}, + author = {Achim D. Brucker}, + keywords = {OCL, UML, formal semantics, theorem proving, Isabelle, HOL-OCL}, + month = {mar}, + note = {ETH Dissertation No. 17097.}, + pdf = {https://www.brucker.ch/bibliography/download/2007/brucker-interactive-2007.pdf}, + school = {ETH Zurich}, + title = {An Interactive Proof Environment for Object-oriented Specifications}, + url = {https://www.brucker.ch/bibliography/abstract/brucker-interactive-2007}, + year = {2007}, +} + +@InCollection{ brucker.ea:standard-compliance-testing:2018, + talk = {talk:brucker.ea:standard-compliance-testing:2018}, + abstract = {Most popular technologies are based on informal or + semiformal standards that lack a rigid formal semantics. + Typical examples include web technologies such as the DOM + or HTML, which are defined by the Web Hypertext Application + Technology Working Group (WHATWG) and the World Wide Web + Consortium (W3C). While there might be API specifications + and test cases meant to assert the compliance of a certain + implementation, the actual standard is rarely accompanied + by a formal model that would lend itself for, e.g., + verifying the security or safety properties of real + systems. + + Even when such a formalization of a standard exists, two + important questions arise: first, to what extend does the + formal model comply to the standard and, second, to what + extend does the implementation comply to the formal model + and the assumptions made during the verification? In this + paper, we present an approach that brings all three + involved artifacts - the (semi-)formal standard, the + formalization of the standard, and the implementations - + closer together by combining verification, symbolic + execution, and specification based testing.}, + keywords = {standard compliance, compliance tests, DOM}, + location = {Toulouse, France}, + author = {Achim D. Brucker and Michael Herzberg}, + booktitle = {{TAP} 2018: Tests And Proofs}, + language = {USenglish}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + number = 10889, + editor = {Cathrine Dubois and Burkhart Wolff}, + title = {Formalizing (Web) Standards: An Application of Test and + Proof}, + categories = {holtestgen, websecurity}, + classification= {conference}, + areas = {formal methods, software engineering}, + public = {yes}, + year = 2018, + doi = {10.1007/978-3-319-92994-1_9}, + pages = {159--166}, + isbn = {978-3-642-38915-3}, + pdf = {http://www.brucker.ch/bibliography/download/2018/brucker.ea-standard-compliance-testing-2018.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-standard-compliance-testing-2018} +} + + +@InCollection{ brucker.ea:interactive:2005, + keywords = {symbolic test case generations, black box testing, white + box testing, theorem proving, interactive testing}, + abstract = {HOL-TestGen is a test environment for specification-based + unit testing build upon the proof assistant Isabelle/HOL\@. + While there is considerable skepticism with regard to + interactive theorem provers in testing communities, we + argue that they are a natural choice for (automated) + symbolic computations underlying systematic tests. This + holds in particular for the development on non-trivial + formal test plans of complex software, where some parts of + the overall activity require inherently guidance by a test + engineer. In this paper, we present the underlying methods + for both black box and white box testing in interactive + unit test scenarios. HOL-TestGen can also be understood as + a unifying technical and conceptual framework for + presenting and investigating the variety of unit test + techniques in a logically consistent way. }, + location = {Edinburgh}, + author = {Achim D. Brucker and Burkhart Wolff}, + booktitle = {Formal Approaches to Testing of Software}, + language = {USenglish}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + number = 3997, + doi = {10.1007/11759744_7}, + isbn = {3-540-25109-X}, + editor = {Wolfgang Grieskamp and Carsten Weise}, + pdf = {http://www.brucker.ch/bibliography/download/2005/brucker.ea-interactive-2005.pdf}, + project = {CSFMDOS}, + title = {Interactive Testing using {HOL}-{TestGen}}, + classification= {workshop}, + areas = {formal methods, software}, + categories = {holtestgen}, + year = 2005, + public = {yes}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-interactive-2005} +} + + +@Article{ brucker.ea:theorem-prover:2012, + author = {Achim D. Brucker and Burkhart Wolff}, + journal = j-fac, + publisher = pub-springer, + address = pub-springer:adr, + language = {USenglish}, + categories = {holtestgen}, + title = {On Theorem Prover-based Testing}, + year = 2013, + issn = {0934-5043}, + pages = {683--721}, + volume = 25, + number = 5, + classification= {journal}, + areas = {formal methods, software}, + public = {yes}, + doi = {10.1007/s00165-012-0222-y}, + keywords = {test case generation, domain partitioning, test sequence, + theorem proving, HOL-TestGen}, + abstract = {HOL-TestGen is a specification and test case generation + environment extending the interactive theorem prover + Isabelle/HOL. As such, HOL-TestGen allows for an integrated + workflow supporting interactive theorem proving, test case + generation, and test data generation. + + The HOL-TestGen method is two-staged: first, the original + formula is partitioned into test cases by transformation + into a normal form called test theorem. Second, the test + cases are analyzed for ground instances (the test data) + satisfying the constraints of the test cases. Particular + emphasis is put on the control of explicit test-hypotheses + which can be proven over concrete programs. + + Due to the generality of the underlying framework, our + system can be used for black-box unit, sequence, reactive + sequence and white-box test scenarios. Although based on + particularly clean theoretical foundations, the system can + be applied for substantial case-studies. }, + pdf = {http://www.brucker.ch/bibliography/download/2012/brucker.ea-theorem-prover-2012.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-theorem-prover-2012} +} + + +@Article{ brucker.ea:afp-core-dom:2018, + abstract = {In this AFP entry, we formalize the core of the Document Object Model (DOM). At its core, the DOM defines a tree-like data structure for representing documents in general and HTML documents in particular. It is the heart of any modern web browser. Formalizing the key concepts of the DOM is a prerequisite for the formal reasoning over client-side JavaScript programs and for the analysis of security concepts in modern web browsers. We present a formalization of the core DOM, with focus on the node-tree and the operations defined on node-trees, in Isabelle/HOL. We use the formalization to verify the functional correctness of the most important functions defined in the DOM standard. Moreover, our formalization is 1) extensible, i.e., can be extended without the need of re-proving already proven properties and 2) executable, i.e., we can generate executable code from our specification.}, + author = {Achim D. Brucker and Michael Herzberg}, + date = {2018-12-26}, + file = {https://www.brucker.ch/bibliography/download/2018/brucker.ea-afp-core-dom-outline-2018.pdf}, + filelabel = {Outline}, + issn = {2150-914x}, + journal = {Archive of Formal Proofs}, + month = {dec}, + note = {\url{http://www.isa-afp.org/entries/Core_DOM.html}, Formal proof development}, + pdf = {https://www.brucker.ch/bibliography/download/2018/brucker.ea-afp-core-dom-2018.pdf}, + title = {The Core {DOM}}, + url = {https://www.brucker.ch/bibliography/abstract/brucker.ea-afp-core-dom-2018-a}, + year = {2018}, +} + +@Misc{ whatwg:dom:2019, + key = {whatwg}, + author = {{WHATWG}}, + url = {https://dom.spec.whatwg.org/commit-snapshots/7fa83673430f767d329406d0aed901f296332216/}, + month = feb, + year = 2019, + day = 11, + title = {{DOM} -- Living Standard}, + note = {Last Updated 11 {February} 2019}, + institution = {WHATWG} +} + +@Misc{ bidelman:self-contained:2017, + author = {Eric Bidelman}, + title = {Shadow DOM v1: Self-Contained Web Components}, + month = may, + day = 12, + year = 2017, + url = {https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom} +} + + + +@Article{ brucker.ea:afp-shadow-sc-dom:2020, + author = {Achim D. Brucker and Michael Herzberg}, + title = {Shadow SC DOM: A Formal Model of the Safelty Composable Document Object Model with Shadow Roots}, + journal = {Archive of Formal Proofs}, + month = sep, + year = 2020, + date = {2020-09-28}, + note = {\url{http://www.isa-afp.org/entries/Shadow_SC_DOM.html}, Formal proof development}, + issn = {2150-914x}, + abstract = { In this AFP entry, we extend our formalization of the safely composable DOM with \emph{Shadow + Roots}. Shadow roots are a recent proposal of the web community to support a component-based + development approach for client-side web applications. + + Shadow roots are a significant extension to the DOM standard and, as web standards are condemned to be + backward compatible, such extensions often result in complex specification that may contain unwanted + subtleties that can be detected by a formalization. + + Our Isabelle/HOL formalization is, in the sense of object-orientation, an extension of our + formalization of the core DOM and enjoys the same basic properties, i.e., it is extensible, i.e., can + be extended without the need of re-proving already proven properties and executable, i.e., we can + generate executable code from our specification. We exploit the executability to show that our + formalization complies to the official standard of the W3C, respectively, the WHATWG. }, + public = {yes}, + classification= {formal}, + categories = {websecurity}, + pdf = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-shadow-sc-dom-2020.pdf}, + filelabel = {Outline}, + file = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-shadow-sc-dom-outline-2020.pdf}, + areas = {formal methods, security, software engineering}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-afp-shadow-sc-dom-2020} +} + +@Article{ brucker.ea:afp-dom-components:2020, + author = {Achim D. Brucker and Michael Herzberg}, + title = {A Formalization of Web Components}, + journal = {Archive of Formal Proofs}, + month = sep, + year = 2020, + date = {2020-09-28}, + note = {\url{http://www.isa-afp.org/entries/DOM_Components.html}, Formal proof development}, + issn = {2150-914x}, + public = {yes}, + classification= {formal}, + categories = {websecurity}, + pdf = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-dom-components-2020.pdf}, + filelabel = {Outline}, + file = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-dom-components-outline-2020.pdf}, + areas = {formal methods, security, software engineering}, + abstract = { While the DOM with shadow trees provide the technical basis for defining web components, the DOM + standard neither defines the concept of web components nor specifies the safety properties that web + components should guarantee. Consequently, the standard also does not discuss how or even if the + methods for modifying the DOM respect component boundaries. + + In AFP entry, we present a formally verified model of web components and define safety properties + which ensure that different web components can only interact with each other using well-defined + interfaces. Moreover, our verification of the application programming interface (API) of the DOM + revealed numerous invariants that implementations of the DOM API need to preserve to ensure the + integrity of components. }, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-afp-dom-components-2020} +} + +@Article{ brucker.ea:afp-sc-dom-components:2020, + author = {Achim D. Brucker and Michael Herzberg}, + title = {A Formalization of Safely Composable Web Components}, + journal = {Archive of Formal Proofs}, + month = sep, + year = 2020, + date = {2020-09-28}, + note = {\url{http://www.isa-afp.org/entries/SC_DOM_Components.html}, Formal proof development}, + issn = {2150-914x}, + public = {yes}, + classification= {formal}, + categories = {websecurity}, + pdf = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-sc-dom-components-2020.pdf}, + filelabel = {Outline}, + file = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-sc-dom-components-outline-2020.pdf}, + areas = {formal methods, security, software engineering}, + abstract = { While the (safely composable) DOM with shadow trees provide the technical basis for defining web + components, it does neither defines the concept of web components nor specifies the safety properties + that web components should guarantee. Consequently, the standard also does not discuss how or even if + the methods for modifying the DOM respect component boundaries. In AFP entry, we present a formally + verified model of safely composable web components and define safety properties which ensure that + different web components can only interact with each other using well-defined interfaces. Moreover, + our verification of the application programming interface (API) of the DOM revealed numerous + invariants that implementations of the DOM API need to preserve to ensure the integrity of components. + }, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-afp-sc-dom-components-2020} +} + + + +@Article{ brucker.ea:afp-core-sc-dom:2020, + author = {Achim D. Brucker and Michael Herzberg}, + title = {The Safely Composable {DOM}}, + journal = {Archive of Formal Proofs}, + month = sep, + year = 2020, + date = {2020-09-28}, + note = {\url{http://www.isa-afp.org/entries/Core_SC_DOM.html}, Formal proof development}, + issn = {2150-914x}, + abstract = { In this AFP entry, we formalize the core of the Safely Composable Document Object Model (SC DOM). + The SC DOM improve the standard DOM by strengthening the tree boundaries set by shadow roots: in the + SC DOM, the shadow root is a sub-class of the document class (instead of a base class). + + This modifications also results in changes to some API methods (e.g., getOwnerDocument) to return the + nearest shadow root rather than the document root. As a result, many API methods that, when called on + a node inside a shadow tree, would previously ``break out'' and return or modify nodes that are + possibly outside the shadow tree, now stay within its boundaries. This change in behavior makes + programs that operate on shadow trees more predictable for the developer and allows them to make more + assumptions about other code accessing the DOM. }, + public = {yes}, + classification= {formal}, + categories = {websecurity}, + pdf = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-core-sc-dom-2020.pdf}, + filelabel = {Outline}, + file = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-core-sc-dom-outline-2020.pdf}, + areas = {formal methods, security, software engineering}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-afp-core-sc-dom-2020} +} + +@Article{ brucker.ea:afp-shadow-dom:2020, + author = {Achim D. Brucker and Michael Herzberg}, + title = {Shadow DOM: A Formal Model of the Document Object Model with Shadow Roots}, + journal = {Archive of Formal Proofs}, + month = sep, + year = 2020, + date = {2020-09-28}, + note = {\url{http://www.isa-afp.org/entries/Shadow_DOM.html}, Formal proof development}, + issn = {2150-914x}, + abstract = { In this AFP entry, we extend our formalization of the core DOM with \emph{Shadow Roots}. Shadow + roots are a recent proposal of the web community to support a component-based development approach for + client-side web applications. + + Shadow roots are a significant extension to the DOM standard and, as web standards are condemned to be + backward compatible, such extensions often result in complex specification that may contain unwanted + subtleties that can be detected by a formalization. + + Our Isabelle/HOL formalization is, in the sense of object-orientation, an extension of our + formalization of the core DOM and enjoys the same basic properties, i.e., it is extensible, i.e., can + be extended without the need of re-proving already proven properties and executable, i.e., we can + generate executable code from our specification. We exploit the executability to show that our + formalization complies to the official standard of the W3C, respectively, the WHATWG. }, + public = {yes}, + classification= {formal}, + categories = {websecurity}, + pdf = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-shadow-dom-2020.pdf}, + filelabel = {Outline}, + file = {http://www.brucker.ch/bibliography/download/2020/brucker.ea-afp-shadow-dom-outline-2020.pdf}, + areas = {formal methods, security, software engineering}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-afp-shadow-dom-2020} +} + + + + +@InCollection{ brucker.ea:web-components:2019, + abstract = {The trend towards ever more complex client-side web applications is unstoppable. Compared to + traditional software development, client-side web development lacks a well-established component + model, i.e., a method for easily and safely reusing already developed functionality. To address this + issue, the web community started to adopt shadow trees as part of the Document Object Model (DOM): + shadow trees allow developers to "partition" a DOM instance into parts that should be safely + separated, e.g., code modifying one part should not, unintentionally, affect other parts of the DOM. + + While shadow trees provide the technical basis for defining web components, the DOM standard neither + defines the concept of web components nor specifies the safety properties that web components should + guarantee. Consequently, the standard also does not discuss how or even if the methods for modifying + the DOM respect component boundaries. In this paper, we present a formally verified model of web + components and define safety properties which ensure that different web components can only interact + with each other using well-defined interfaces. Moreover, our verification of the application + programming interface (API) of the DOM revealed numerous invariants that implementations of the DOM + API need to preserve to ensure the integrity of components.}, + keywords = {Web Component, Shadow Tree, DOM, Isabelle/HOL}, + location = {Amsterdam, The Netherlands}, + author = {Achim D. Brucker and Michael Herzberg}, + booktitle = {Formal Aspects of Component Software (FACS)}, + language = {USenglish}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + number = 12018, + isbn = {3-540-25109-X}, + doi = {10.1007/978-3-030-40914-2_3}, + editor = {Sung-Shik Jongmans and Farhad Arbab}, + pdf = {http://www.brucker.ch/bibliography/download/2019/brucker.ea-web-components-2019.pdf}, + title = {A Formally Verified Model of Web Components}, + classification= {conference}, + areas = {formal methods, software}, + year = 2020, + public = {yes}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-web-components-2019} +} + + + +@PhdThesis{herzberg:web-components:2020, + author = {Michael Herzberg}, + title = {Formal Foundations for Provably Safe Web Components}, + school = {The University of Sheffield}, + year = {2020} +} + diff --git a/DOM_Components/document/root.tex b/DOM_Components/document/root.tex new file mode 100644 index 0000000..c594de3 --- /dev/null +++ b/DOM_Components/document/root.tex @@ -0,0 +1,238 @@ +\documentclass[10pt,DIV16,a4paper,abstract=true,twoside=semi,openright] +{scrreprt} +\usepackage[USenglish]{babel} +\usepackage[numbers, sort&compress]{natbib} +\usepackage{isabelle,isabellesym} +\usepackage{booktabs} +\usepackage{paralist} +\usepackage{graphicx} +\usepackage{amssymb} +\usepackage{xspace} +\usepackage{xcolor} +\usepackage{listings} +\lstloadlanguages{HTML} +\usepackage[]{mathtools} +\usepackage[pdfpagelabels, pageanchor=false, plainpages=false]{hyperref} +\lstdefinestyle{html}{language=XML, + basicstyle=\ttfamily, + commentstyle=\itshape, + keywordstyle=\color{blue}, + ndkeywordstyle=\color{blue}, +} +\lstdefinestyle{displayhtml}{style=html, + floatplacement={tbp}, + captionpos=b, + framexleftmargin=0pt, + basicstyle=\ttfamily\scriptsize, + backgroundcolor=\color{black!2}, + frame=lines, +} +\lstnewenvironment{html}[1][]{\lstset{style=displayhtml, #1}}{} +\def\inlinehtml{\lstinline[style=html, columns=fullflexible]} + \newsavebox{\fstlst} + \newsavebox{\sndlst} +\usepackage[caption=false]{subfig} + +\pagestyle{headings} +\isabellestyle{default} +\setcounter{tocdepth}{1} +\newcommand{\ie}{i.\,e.\xspace} +\newcommand{\eg}{e.\,g.\xspace} +\newcommand{\thy}{\isabellecontext} +\renewcommand{\isamarkupsection}[1]{% + \begingroup% + \def\isacharunderscore{\textunderscore}% + \section{#1 (\thy)}% + \endgroup% +} + +\title{A Formalization of Web Components} +\author{Achim~D.~Brucker \and Michael~Herzberg}% +\publishers{ + \footnotemark[1]~Department of Computer Science, University of Exeter, Exeter, UK\texorpdfstring{\\}{, } + \texttt{a.brucker@exeter.ac.uk}\\[2em] + % + \footnotemark[2]~ Department of Computer Science, The University of Sheffield, Sheffield, UK\texorpdfstring{\\}{, } + \texttt{msherzberg1@sheffield.ac.uk} +} +\begin{document} + \maketitle + \begin{abstract} + \begin{quote} + While the DOM with shadow trees provide the technical basis for + defining web components, the DOM standard neither defines the + concept of web components nor specifies the safety properties + that web components should guarantee. Consequently, the standard + also does not discuss how or even if the methods for modifying + the DOM respect component boundaries. + + In AFP entry, we present a formally verified model of web + components and define safety properties which ensure that + different web components can only interact with each other using + well-defined interfaces. Moreover, our verification of the + application programming interface (API) of the DOM revealed + numerous invariants that implementations of the DOM API need to + preserve to ensure the integrity of components. + + \bigskip + \noindent{\textbf{Keywords:} Web Components, DOM} + \end{quote} + \end{abstract} + + +\tableofcontents +\cleardoublepage + +\chapter{Introduction} +The trend towards ever more complex client-side web applications is +unstoppable. Compared to traditional software development, client-side +web development lacks a well-established component model which allows +easily and safely reusing implementations. The Document Object Model +(DOM) essentially defines a tree-like data structure (the \emph{node +tree}) for representing documents in general and HTML documents in +particular. + +\emph{Shadow trees} are a recent addition to the DOM +standard~\cite{whatwg:dom:2019} to enable web developers to partition +the node tree into ``sub-trees.'' The vision of shadow trees is to +enable web developers to provide a library of re-usable and +customizable widgets. For example, let us consider a multi-tab view +called \emph{Fancy Tab}, which is a simplified version +of~\cite{bidelman:self-contained:2017}. + +\begin{figure}[b] + \begin{lrbox}{\fstlst}% + \begin{minipage}{.34\linewidth} + \centering + \includegraphics[width=\linewidth]{fancytabs-normal} + \end{minipage} + \end{lrbox} + \begin{lrbox}{\sndlst}% + \begin{minipage}{.63\linewidth} + \begin{html}[basicstyle=\ttfamily\scriptsize] + + + + +

content panel 1
+
    +
  • News Item 1
  • +
  • News Item 2
  • +
  • News Item 3
  • +
+
content panel 3
+ + \end{html} + \end{minipage} + \end{lrbox} + \subfloat[\label{fig:running-example-user} + User view + ]{\usebox{\fstlst}}% + \hfill% + \subfloat[\label{fig:running-example-consumer} + Consumer view + ]{\usebox{\sndlst}} + \caption{A simple example: a fancy tab component.}\label{fig:running-example} +\end{figure} + +The left-hand side of \autoref{fig:running-example} shows the rendered +output of the widget in use while the right-hand side shows the HTML +source code snippet. It provides a custom HTML tag +\inlinehtml{} using an HTML template that developers can +use to include the widget. Its children will be rendered inside the +widget, more precisely, inside its \emph{slots} (elements of type +\inlinehtml{slot}). It has a slot called ``title'' and a default +slot, which receives all children that do not specify a ``slot'' +attribute. + +It is important to understand that slotting does \emph{not change} the +structure of the DOM (\ie, the underlying pointer graph): instead, +slotting is implemented using special element attributes such as +``slot,'' which control the final rendering. The DOM standard +specifies methods that inspect the effect of these attributes such as +\texttt{assigned\_slot}, but the majority of DOM methods do not +consider the semantics of these attributes and therefore do not +traverse into shadow trees. + +This provides an important boundary for client-side code. For example, +a JavaScript program coming from the widget developer that changes the +style attributes of the ``Previous Tab'' and ``Next Tab'' buttons in the lower +corners of the widget will not affect buttons belonging to other parts +coming from outside, \ie, the application of the widget consumer. +Similarly, a JavaScript program that changes the styles of buttons +outside of Fancy Tab, such as the navigation buttons, will not have +any effect on them, even in the case of duplicate identifiers. + +Sadly, the DOM standard neither defines the concept of web components +nor specifies the safety properties that they should guarantee, not +even informally. Consequently, the standard also does not discuss how +or even if the methods for modifying the node tree respect component +boundaries. Thus, shadow roots are only the very first step in +defining a safe web component model. + +Earlier~\cite{brucker.ea:core-dom:2018,brucker.ea:afp-core-dom:2018}, +we presented a formalization of the ``flat'' DOM (called Core DOM) +without any support for shadow trees or components. We then extended +this formalisation with support for shadow trees and +slots~\cite{brucker.ea:afp-shadow-dom:2020}. + +In this AFP entries, we use the basis provided by our earlier work for +defining a \emph{formally verified model of web components} in general +and, in particular, the notion of \emph{weak} and \emph{strong + component safety}. For all methods that query, modify, or transform +the DOM, we formally analyze their level of component safety. In more +detail, the contribution of this AFP entry is four-fold: +\begin{enumerate} +\item We provide a formal model of web components and their safety + guarantees to web developers, enabling a compositional development + of web applications, +\item for each method, we formally verify that it is either weakly or + strongly component safe, or we provide a proof showing + that it is not component safe, +\item we fill the gaps in the standard by explicitly formalizing + invariants that are left out in the standard. These invariants are + required to ensure that methods in the standard preserve a valid + node tree. Finally, +\item we present a formal model of the DOM with shadow roots including + the methods for querying, modifying, and transforming DOM instances + with shadow roots. +\end{enumerate} +Overall, our work gives web developers the guarantee that their code +will respect the component boundaries as long as they abstain from or +are careful when using certain DOM methods such as +\texttt{appendChild} or \texttt{ownerDocument}. + +The rest of this document is automatically generated from the +formalization in Isabelle/HOL, i.e., all content is checked by +Isabelle (we refer readers interested in a more high-level +presentation of the work to \cite{herzberg:web-components:2020, + brucker.ea:web-components:2019}. The structure follows the theory +dependencies (see \autoref{fig:session-graph}). + +\begin{figure} + \centering + \includegraphics[width=.8\textwidth]{session_graph} + \caption{The Dependency Graph of the Isabelle Theories.\label{fig:session-graph}} +\end{figure} + +\clearpage + +\chapter{Web Components} +\label{cha:components} +\input{Core_DOM_Components.tex} +\input{Shadow_DOM_Components.tex} + +\chapter{Example} +\label{cha:example} +\input{fancy_tabs.tex} + +{\small + \bibliographystyle{abbrvnat} + \bibliography{root} +} +\end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: