let node_insert (parent: node_ref) (child: node_ref) (pos: int) (b: b)
  : b * output_event list * task list =
    assert (node_valid parent b);
    assert (node_valid child b);
    if List.mem parent (node_descendents true parent b) then
      failwith "node_insert";
    let (b', oes1) = node_remove child b in
    begin match node_assoc_valid parent b' with
    | Div_node(id, children) ->
        let children' = insert_in_list child children pos in
        let dn' = Div_node(id, children') in
        let b'' = node_update parent dn' b' in
        begin match node_page parent b'' with
        | None -> (b'', oes1, [])
        | Some(pr) ->
            let (b''', oes2, ts) = process_node_scripts pr child b'' in
            (b''', oes1 @ [ page_update_event pr b''' ] @ oes2, ts)
        end
    | _ -> failwith "node_insert"
    end