summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-04-15 11:02:53 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-04-15 11:02:53 +0000
commitb50dc50a2b25c7cc77843b25adc41575cfce7fd6 (patch)
tree68d81123fda9d7df3aa15375e12ea034896a1c87 /src
parent051158ffe97eb9b4a1a4b9b5ea719c7e38509200 (diff)
downloadlibhubbub-b50dc50a2b25c7cc77843b25adc41575cfce7fd6.tar.gz
libhubbub-b50dc50a2b25c7cc77843b25adc41575cfce7fd6.tar.bz2
Manually merge r7070 into trunk
svn path=/trunk/hubbub/; revision=7082
Diffstat (limited to 'src')
-rw-r--r--src/treebuilder/after_after_body.c17
-rw-r--r--src/treebuilder/after_after_frameset.c9
-rw-r--r--src/treebuilder/after_body.c11
-rw-r--r--src/treebuilder/after_frameset.c12
-rw-r--r--src/treebuilder/after_head.c32
-rw-r--r--src/treebuilder/before_head.c9
-rw-r--r--src/treebuilder/before_html.c21
-rw-r--r--src/treebuilder/generic_rcdata.c8
-rw-r--r--src/treebuilder/in_body.c1127
-rw-r--r--src/treebuilder/in_caption.c14
-rw-r--r--src/treebuilder/in_cell.c21
-rw-r--r--src/treebuilder/in_column_group.c19
-rw-r--r--src/treebuilder/in_foreign_content.c28
-rw-r--r--src/treebuilder/in_frameset.c26
-rw-r--r--src/treebuilder/in_head.c47
-rw-r--r--src/treebuilder/in_head_noscript.c8
-rw-r--r--src/treebuilder/in_row.c45
-rw-r--r--src/treebuilder/in_select.c75
-rw-r--r--src/treebuilder/in_select_in_table.c6
-rw-r--r--src/treebuilder/in_table.c86
-rw-r--r--src/treebuilder/in_table_body.c37
-rw-r--r--src/treebuilder/initial.c33
-rw-r--r--src/treebuilder/internal.h37
-rw-r--r--src/treebuilder/treebuilder.c398
24 files changed, 1338 insertions, 788 deletions
diff --git a/src/treebuilder/after_after_body.c b/src/treebuilder/after_after_body.c
index 372d12c..9644e3d 100644
--- a/src/treebuilder/after_after_body.c
+++ b/src/treebuilder/after_after_body.c
@@ -19,7 +19,9 @@
*
* \param treebuilder The treebuilder instance
* \param token The token to handle
- * \return True to reprocess token, false otherwise
+ * \return HUBBUB_OK on completion,
+ * HUBBUB_REPROCESS to reprocess the token,
+ * appropriate error otherwise
*/
hubbub_error handle_after_after_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
@@ -28,18 +30,17 @@ hubbub_error handle_after_after_body(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- if (process_characters_expect_whitespace(treebuilder,
- token, true)) {
+ err = process_characters_expect_whitespace(treebuilder,
+ token, true);
+ if (err == HUBBUB_REPROCESS)
treebuilder->context.mode = IN_BODY;
- err = HUBBUB_REPROCESS;
- }
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.document);
break;
case HUBBUB_TOKEN_DOCTYPE:
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
break;
case HUBBUB_TOKEN_START_TAG:
{
@@ -48,7 +49,7 @@ hubbub_error handle_after_after_body(hubbub_treebuilder *treebuilder,
if (type == HTML) {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else {
/** \todo parse error */
treebuilder->context.mode = IN_BODY;
diff --git a/src/treebuilder/after_after_frameset.c b/src/treebuilder/after_after_frameset.c
index 0b1617a..f068714 100644
--- a/src/treebuilder/after_after_frameset.c
+++ b/src/treebuilder/after_after_frameset.c
@@ -28,14 +28,13 @@ hubbub_error handle_after_after_frameset(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- if (process_characters_expect_whitespace(treebuilder,
- token, true)) {
+ err = process_characters_expect_whitespace(treebuilder,
+ token, true);
+ if (err == HUBBUB_REPROCESS)
treebuilder->context.mode = IN_FRAMESET;
- err = HUBBUB_REPROCESS;
- }
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.document);
break;
case HUBBUB_TOKEN_END_TAG:
diff --git a/src/treebuilder/after_body.c b/src/treebuilder/after_body.c
index beaed69..42e982b 100644
--- a/src/treebuilder/after_body.c
+++ b/src/treebuilder/after_body.c
@@ -30,7 +30,6 @@ hubbub_error handle_after_body(hubbub_treebuilder *treebuilder,
case HUBBUB_TOKEN_CHARACTER:
{
/* mostly cribbed from process_characters_expect_whitespace */
-
const uint8_t *data = token->data.character.ptr;
size_t len = token->data.character.len;
size_t c;
@@ -42,12 +41,14 @@ hubbub_error handle_after_body(hubbub_treebuilder *treebuilder,
break;
}
- /* Non-whitespace characters in token, so handle as in body */
+ /* Whitespace characters in token, so handle as in body */
if (c > 0) {
hubbub_token temp = *token;
temp.data.character.len = c;
- handle_in_body(treebuilder, &temp);
+ err = handle_in_body(treebuilder, &temp);
+ if (err != HUBBUB_OK)
+ return err;
}
/* Anything else, switch to in body */
@@ -62,7 +63,7 @@ hubbub_error handle_after_body(hubbub_treebuilder *treebuilder,
}
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
0].node);
break;
@@ -76,7 +77,7 @@ hubbub_error handle_after_body(hubbub_treebuilder *treebuilder,
if (type == HTML) {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else {
/** \todo parse error */
treebuilder->context.mode = IN_BODY;
diff --git a/src/treebuilder/after_frameset.c b/src/treebuilder/after_frameset.c
index a94eb86..04888ab 100644
--- a/src/treebuilder/after_frameset.c
+++ b/src/treebuilder/after_frameset.c
@@ -28,13 +28,17 @@ hubbub_error handle_after_frameset(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- if (process_characters_expect_whitespace(treebuilder,
- token, true)) {
+ err = process_characters_expect_whitespace(treebuilder,
+ token, true);
+ if (err == HUBBUB_REPROCESS) {
/** \todo parse error */
+
+ /* Ignore the token */
+ err = HUBBUB_OK;
}
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -47,7 +51,7 @@ hubbub_error handle_after_frameset(hubbub_treebuilder *treebuilder,
&token->data.tag.name);
if (type == HTML) {
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else if (type == NOFRAMES) {
err = handle_in_head(treebuilder, token);
} else {
diff --git a/src/treebuilder/after_head.c b/src/treebuilder/after_head.c
index 9af0796..6305f4c 100644
--- a/src/treebuilder/after_head.c
+++ b/src/treebuilder/after_head.c
@@ -33,7 +33,7 @@ hubbub_error handle_after_head(hubbub_treebuilder *treebuilder,
token, true);
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -47,12 +47,14 @@ hubbub_error handle_after_head(hubbub_treebuilder *treebuilder,
if (type == HTML) {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else if (type == BODY) {
handled = true;
} else if (type == FRAMESET) {
- insert_element(treebuilder, &token->data.tag, true);
- treebuilder->context.mode = IN_FRAMESET;
+ err = insert_element(treebuilder, &token->data.tag,
+ true);
+ if (err == HUBBUB_OK)
+ treebuilder->context.mode = IN_FRAMESET;
} else if (type == BASE || type == LINK || type == META ||
type == NOFRAMES || type == SCRIPT ||
type == STYLE || type == TITLE) {
@@ -60,25 +62,26 @@ hubbub_error handle_after_head(hubbub_treebuilder *treebuilder,
element_type otype;
void *node;
uint32_t index;
+ hubbub_error e;
/** \todo parse error */
- if (!element_stack_push(treebuilder,
+ err = element_stack_push(treebuilder,
HUBBUB_NS_HTML,
HEAD,
- treebuilder->context.head_element)) {
- /** \todo errors */
- }
+ treebuilder->context.head_element);
+ if (err != HUBBUB_OK)
+ return err;
index = treebuilder->context.current_node;
/* Process as "in head" */
err = handle_in_head(treebuilder, token);
- if (!element_stack_remove(treebuilder, index,
- &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_remove(treebuilder, index,
+ &ns, &otype, &node);
+ /* Can't result in error -- ensure this. */
+ assert(e == HUBBUB_OK);
/* No need to unref node as we never increased
* its reference count when pushing it on the stack */
@@ -107,6 +110,7 @@ hubbub_error handle_after_head(hubbub_treebuilder *treebuilder,
}
if (handled || err == HUBBUB_REPROCESS) {
+ hubbub_error e;
hubbub_tag tag;
if (err == HUBBUB_REPROCESS) {
@@ -121,7 +125,9 @@ hubbub_error handle_after_head(hubbub_treebuilder *treebuilder,
tag = token->data.tag;
}
- insert_element(treebuilder, &tag, true);
+ e = insert_element(treebuilder, &tag, true);
+ if (e != HUBBUB_OK)
+ return e;
treebuilder->context.mode = IN_BODY;
}
diff --git a/src/treebuilder/before_head.c b/src/treebuilder/before_head.c
index 19bf800..15e82a8 100644
--- a/src/treebuilder/before_head.c
+++ b/src/treebuilder/before_head.c
@@ -33,7 +33,7 @@ hubbub_error handle_before_head(hubbub_treebuilder *treebuilder,
token, false);
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -47,7 +47,7 @@ hubbub_error handle_before_head(hubbub_treebuilder *treebuilder,
if (type == HTML) {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else if (type == HEAD) {
handled = true;
} else {
@@ -74,6 +74,7 @@ hubbub_error handle_before_head(hubbub_treebuilder *treebuilder,
}
if (handled || err == HUBBUB_REPROCESS) {
+ hubbub_error e;
hubbub_tag tag;
if (err == HUBBUB_REPROCESS) {
@@ -88,7 +89,9 @@ hubbub_error handle_before_head(hubbub_treebuilder *treebuilder,
tag = token->data.tag;
}
- insert_element(treebuilder, &tag, true);
+ e = insert_element(treebuilder, &tag, true);
+ if (e != HUBBUB_OK)
+ return e;
treebuilder->tree_handler->ref_node(
treebuilder->tree_handler->ctx,
diff --git a/src/treebuilder/before_html.c b/src/treebuilder/before_html.c
index d5a0d22..1ed3717 100644
--- a/src/treebuilder/before_html.c
+++ b/src/treebuilder/before_html.c
@@ -32,7 +32,7 @@ hubbub_error handle_before_html(hubbub_treebuilder *treebuilder,
/** \todo parse error */
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.document);
break;
case HUBBUB_TOKEN_CHARACTER:
@@ -59,7 +59,7 @@ hubbub_error handle_before_html(hubbub_treebuilder *treebuilder,
if (handled || err == HUBBUB_REPROCESS) {
- int success;
+ hubbub_error e;
void *html, *appended;
/* We can't use insert_element() here, as it assumes
@@ -78,31 +78,30 @@ hubbub_error handle_before_html(hubbub_treebuilder *treebuilder,
tag.n_attributes = 0;
tag.attributes = NULL;
- success = treebuilder->tree_handler->create_element(
+ e = treebuilder->tree_handler->create_element(
treebuilder->tree_handler->ctx,
&tag, &html);
} else {
- success = treebuilder->tree_handler->create_element(
+ e = treebuilder->tree_handler->create_element(
treebuilder->tree_handler->ctx,
&token->data.tag, &html);
}
- if (success != 0) {
- /** \todo errors */
- }
+ if (e != HUBBUB_OK)
+ return e;
- success = treebuilder->tree_handler->append_child(
+ e = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
treebuilder->context.document,
html, &appended);
- if (success != 0) {
- /** \todo errors */
- }
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
html);
+ if (e != HUBBUB_OK)
+ return e;
+
/* We can't use element_stack_push() here, as it
* assumes that current_node is pointing at the index
* before the one to insert at. For the first entry in
diff --git a/src/treebuilder/generic_rcdata.c b/src/treebuilder/generic_rcdata.c
index 627068a..2da8d44 100644
--- a/src/treebuilder/generic_rcdata.c
+++ b/src/treebuilder/generic_rcdata.c
@@ -50,7 +50,7 @@ hubbub_error handle_generic_rcdata(hubbub_treebuilder *treebuilder,
if (chars.len == 0)
break;
- append_text(treebuilder, &chars);
+ err = append_text(treebuilder, &chars);
}
break;
case HUBBUB_TOKEN_END_TAG:
@@ -85,14 +85,14 @@ hubbub_error handle_generic_rcdata(hubbub_treebuilder *treebuilder,
}
if (done) {
+ hubbub_error e;
hubbub_ns ns;
element_type otype;
void *node;
/* Pop the current node from the stack */
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
diff --git a/src/treebuilder/in_body.c b/src/treebuilder/in_body.c
index ce3032e..58d145a 100644
--- a/src/treebuilder/in_body.c
+++ b/src/treebuilder/in_body.c
@@ -15,6 +15,14 @@
#undef DEBUG_IN_BODY
+/* In body mode states */
+enum {
+ IBS_INITIAL = 0,
+ IBS_DONE_FORMATTING_LIST = 1,
+ IBS_REMOVED_NODE = 2,
+ IBS_CLOSED_P = 3,
+};
+
/**
* Bookmark for formatting list. Used in adoption agency
*/
@@ -23,90 +31,93 @@ typedef struct bookmark {
formatting_list_entry *next; /**< Next entry */
} bookmark;
-static void process_character(hubbub_treebuilder *treebuilder,
+static hubbub_error process_character(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static bool process_start_tag(hubbub_treebuilder *treebuilder,
+static hubbub_error process_start_tag(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static bool process_end_tag(hubbub_treebuilder *treebuilder,
+static hubbub_error process_end_tag(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_html_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_html_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_body_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_body_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_frameset_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_frameset_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_container_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_container_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_hN_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_hN_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_form_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_form_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token, element_type type);
-static void process_plaintext_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_plaintext_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_a_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_a_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_presentational_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_presentational_in_body(
+ hubbub_treebuilder *treebuilder,
const hubbub_token *token, element_type type);
-static void process_nobr_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_nobr_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_button_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_button_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_applet_marquee_object_in_body(
+static hubbub_error process_applet_marquee_object_in_body(
hubbub_treebuilder *treebuilder, const hubbub_token *token,
element_type type);
-static void process_hr_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_hr_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_image_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_image_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_isindex_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_isindex_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_textarea_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_textarea_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_select_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_select_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_opt_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_opt_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static void process_phrasing_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_phrasing_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token);
-static bool process_0body_in_body(hubbub_treebuilder *treebuilder);
-static void process_0container_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_0body_in_body(hubbub_treebuilder *treebuilder);
+static hubbub_error process_0container_in_body(hubbub_treebuilder *treebuilder,
element_type type);
-static void process_0form_in_body(hubbub_treebuilder *treebuilder);
-static void process_0p_in_body(hubbub_treebuilder *treebuilder);
-static void process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_0form_in_body(hubbub_treebuilder *treebuilder);
+static hubbub_error process_0p_in_body(hubbub_treebuilder *treebuilder);
+static hubbub_error process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
element_type type);
-static void process_0h_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_0h_in_body(hubbub_treebuilder *treebuilder,
element_type type);
-static void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_0presentational_in_body(
+ hubbub_treebuilder *treebuilder,
element_type type);
-static void process_0applet_button_marquee_object_in_body(
+static hubbub_error process_0applet_button_marquee_object_in_body(
hubbub_treebuilder *treebuilder, element_type type);
-static void process_0br_in_body(hubbub_treebuilder *treebuilder);
-static void process_0generic_in_body(hubbub_treebuilder *treebuilder,
+static hubbub_error process_0br_in_body(hubbub_treebuilder *treebuilder);
+static hubbub_error process_0generic_in_body(hubbub_treebuilder *treebuilder,
element_type type);
-static bool aa_find_and_validate_formatting_element(
+static hubbub_error aa_find_and_validate_formatting_element(
hubbub_treebuilder *treebuilder, element_type type,
formatting_list_entry **element);
static formatting_list_entry *aa_find_formatting_element(
hubbub_treebuilder *treebuilder, element_type type);
-static bool aa_find_furthest_block(hubbub_treebuilder *treebuilder,
+static hubbub_error aa_find_furthest_block(hubbub_treebuilder *treebuilder,
formatting_list_entry *formatting_element,
uint32_t *furthest_block);
-static void aa_remove_from_parent(hubbub_treebuilder *treebuilder, void *node);
-static void *aa_reparent_node(hubbub_treebuilder *treebuilder, void *node,
- void *new_parent);
-static void aa_find_bookmark_location_reparenting_misnested(
+static hubbub_error aa_reparent_node(hubbub_treebuilder *treebuilder,
+ void *node, void *new_parent, void **reparented);
+static hubbub_error aa_find_bookmark_location_reparenting_misnested(
hubbub_treebuilder *treebuilder,
uint32_t formatting_element, uint32_t *furthest_block,
bookmark *bookmark, uint32_t *last_node);
-static void aa_remove_element_stack_item(hubbub_treebuilder *treebuilder,
+static hubbub_error aa_remove_element_stack_item(
+ hubbub_treebuilder *treebuilder,
uint32_t index, uint32_t limit);
-static void aa_clone_and_replace_entries(hubbub_treebuilder *treebuilder,
+static hubbub_error aa_clone_and_replace_entries(
+ hubbub_treebuilder *treebuilder,
formatting_list_entry *element);
@@ -137,10 +148,10 @@ hubbub_error handle_in_body(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- process_character(treebuilder, token);
+ err = process_character(treebuilder, token);
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -186,13 +197,21 @@ hubbub_error handle_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_character(hubbub_treebuilder *treebuilder,
+hubbub_error process_character(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+ hubbub_error err = HUBBUB_OK;
hubbub_string dummy = token->data.character;
+ bool lr_flag = treebuilder->context.strip_leading_lr;
const uint8_t *p;
- reconstruct_active_formatting_list(treebuilder);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->context.mode_state = IBS_DONE_FORMATTING_LIST;
+ }
if (treebuilder->context.strip_leading_lr) {
const uint8_t *str = dummy.ptr;
@@ -205,8 +224,15 @@ void process_character(hubbub_treebuilder *treebuilder,
treebuilder->context.strip_leading_lr = false;
}
- if (dummy.len)
- append_text(treebuilder, &dummy);
+ if (dummy.len) {
+ err = append_text(treebuilder, &dummy);
+ if (err != HUBBUB_OK) {
+ /* Restore LR stripping flag */
+ treebuilder->context.strip_leading_lr = lr_flag;
+
+ return err;
+ }
+ }
if (treebuilder->context.frameset_ok) {
for (p = dummy.ptr; p < dummy.ptr + dummy.len; p++) {
@@ -217,6 +243,10 @@ void process_character(hubbub_treebuilder *treebuilder,
}
}
}
+
+ treebuilder->context.mode_state = IBS_INITIAL;
+
+ return HUBBUB_OK;
}
/**
@@ -224,9 +254,11 @@ void process_character(hubbub_treebuilder *treebuilder,
*
* \param treebuilder The treebuilder instance
* \param token The token to process
- * \return True to reprocess the token
+ * \return HUBBUB_OK on success,
+ * HUBBUB_REPROCESS to reprocess the token,
+ * appropriate error otherwise.
*/
-bool process_start_tag(hubbub_treebuilder *treebuilder,
+hubbub_error process_start_tag(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
hubbub_error err = HUBBUB_OK;
@@ -234,17 +266,16 @@ bool process_start_tag(hubbub_treebuilder *treebuilder,
&token->data.tag.name);
if (type == HTML) {
- process_html_in_body(treebuilder, token);
+ err = process_html_in_body(treebuilder, token);
} else if (type == BASE || type == COMMAND || type == LINK ||
type == META || type == NOFRAMES || type == SCRIPT ||
type == STYLE || type == TITLE) {
/* Process as "in head" */
err = handle_in_head(treebuilder, token);
} else if (type == BODY) {
- process_body_in_body(treebuilder, token);
+ err = process_body_in_body(treebuilder, token);
} else if (type == FRAMESET) {
- process_frameset_in_body(treebuilder, token);
- treebuilder->context.mode = IN_FRAMESET;
+ err = process_frameset_in_body(treebuilder, token);
} else if (type == ADDRESS || type == ARTICLE || type == ASIDE ||
type == BLOCKQUOTE || type == CENTER ||
type == DATAGRID || type == DETAILS ||
@@ -254,73 +285,96 @@ bool process_start_tag(hubbub_treebuilder *treebuilder,
type == HEADER || type == MENU || type == NAV ||
type == OL || type == P || type == SECTION ||
type == UL) {
- process_container_in_body(treebuilder, token);
+ err = process_container_in_body(treebuilder, token);
} else if (type == H1 || type == H2 || type == H3 ||
type == H4 || type == H5 || type == H6) {
- process_hN_in_body(treebuilder, token);
+ err = process_hN_in_body(treebuilder, token);
} else if (type == PRE || type == LISTING) {
- process_container_in_body(treebuilder, token);
+ err = process_container_in_body(treebuilder, token);
- treebuilder->context.strip_leading_lr = true;
- treebuilder->context.frameset_ok = false;
+ if (err == HUBBUB_OK) {
+ treebuilder->context.strip_leading_lr = true;
+ treebuilder->context.frameset_ok = false;
+ }
} else if (type == FORM) {
- process_form_in_body(treebuilder, token);
+ err = process_form_in_body(treebuilder, token);
} else if (type == DD || type == DT || type == LI) {
- process_dd_dt_li_in_body(treebuilder, token, type);
+ err = process_dd_dt_li_in_body(treebuilder, token, type);
} else if (type == PLAINTEXT) {
- process_plaintext_in_body(treebuilder, token);
+ err = process_plaintext_in_body(treebuilder, token);
} else if (type == A) {
- process_a_in_body(treebuilder, token);
+ err = process_a_in_body(treebuilder, token);
} else if (type == B || type == BIG || type == CODE || type == EM ||
type == FONT || type == I || type == S ||
type == SMALL || type == STRIKE ||
type == STRONG || type == TT || type == U) {
- process_presentational_in_body(treebuilder,
+ err = process_presentational_in_body(treebuilder,
token, type);
} else if (type == NOBR) {
- process_nobr_in_body(treebuilder, token);
+ err = process_nobr_in_body(treebuilder, token);
} else if (type == BUTTON) {
- process_button_in_body(treebuilder, token);
+ err = process_button_in_body(treebuilder, token);
} else if (type == APPLET || type == MARQUEE ||
type == OBJECT) {
- process_applet_marquee_object_in_body(treebuilder,
+ err = process_applet_marquee_object_in_body(treebuilder,
token, type);
} else if (type == XMP) {
- reconstruct_active_formatting_list(treebuilder);
- treebuilder->context.frameset_ok = false;
- parse_generic_rcdata(treebuilder, token, false);
- } else if (type == TABLE) {
- process_container_in_body(treebuilder, token);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->context.mode_state =
+ IBS_DONE_FORMATTING_LIST;
+ }
treebuilder->context.frameset_ok = false;
- treebuilder->context.element_stack[current_table(treebuilder)]
- .tainted = false;
- treebuilder->context.mode = IN_TABLE;
+ err = parse_generic_rcdata(treebuilder, token, false);
+ } else if (type == TABLE) {
+ err = process_container_in_body(treebuilder, token);
+ if (err == HUBBUB_OK) {
+ treebuilder->context.frameset_ok = false;
+
+ treebuilder->context.element_stack[
+ current_table(treebuilder)].tainted = false;
+ treebuilder->context.mode = IN_TABLE;
+ }
} else if (type == AREA || type == BASEFONT ||
type == BGSOUND || type == BR ||
type == EMBED || type == IMG || type == INPUT ||
type == PARAM || type == SPACER || type == WBR) {
- reconstruct_active_formatting_list(treebuilder);
- insert_element(treebuilder, &token->data.tag, false);
- treebuilder->context.frameset_ok = false;
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->context.mode_state =
+ IBS_DONE_FORMATTING_LIST;
+ }
+
+ err = insert_element(treebuilder, &token->data.tag, false);
+ if (err == HUBBUB_OK)
+ treebuilder->context.frameset_ok = false;
} else if (type == HR) {
- process_hr_in_body(treebuilder, token);
+ err = process_hr_in_body(treebuilder, token);
} else if (type == IMAGE) {
- process_image_in_body(treebuilder, token);
+ err = process_image_in_body(treebuilder, token);
} else if (type == ISINDEX) {
- process_isindex_in_body(treebuilder, token);
+ err = process_isindex_in_body(treebuilder, token);
} else if (type == TEXTAREA) {
- process_textarea_in_body(treebuilder, token);
+ err = process_textarea_in_body(treebuilder, token);
} else if (type == IFRAME || type == NOEMBED ||
type == NOFRAMES ||
(treebuilder->context.enable_scripting &&
type == NOSCRIPT)) {
if (type == IFRAME)
treebuilder->context.frameset_ok = false;
- parse_generic_rcdata(treebuilder, token, false);
+ err = parse_generic_rcdata(treebuilder, token, false);
} else if (type == SELECT) {
- process_select_in_body(treebuilder, token);
+ err = process_select_in_body(treebuilder, token);
+ if (err != HUBBUB_OK)
+ return err;
if (treebuilder->context.mode == IN_BODY) {
treebuilder->context.mode = IN_SELECT;
@@ -333,13 +387,21 @@ bool process_start_tag(hubbub_treebuilder *treebuilder,
treebuilder->context.mode = IN_SELECT_IN_TABLE;
}
} else if (type == OPTGROUP || type == OPTION) {
- process_opt_in_body(treebuilder, token);
+ err = process_opt_in_body(treebuilder, token);
} else if (type == RP || type == RT) {
/** \todo ruby */
} else if (type == MATH || type == SVG) {
hubbub_tag tag = token->data.tag;
- reconstruct_active_formatting_list(treebuilder);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->context.mode_state =
+ IBS_DONE_FORMATTING_LIST;
+ }
+
adjust_foreign_attributes(treebuilder, &tag);
if (type == SVG) {
@@ -351,13 +413,15 @@ bool process_start_tag(hubbub_treebuilder *treebuilder,
}
if (token->data.tag.self_closing) {
- insert_element(treebuilder, &tag, false);
+ err = insert_element(treebuilder, &tag, false);
/** \todo ack sc flag */
} else {
- insert_element(treebuilder, &tag, true);
- treebuilder->context.second_mode =
- treebuilder->context.mode;
- treebuilder->context.mode = IN_FOREIGN_CONTENT;
+ err = insert_element(treebuilder, &tag, true);
+ if (err == HUBBUB_OK) {
+ treebuilder->context.second_mode =
+ treebuilder->context.mode;
+ treebuilder->context.mode = IN_FOREIGN_CONTENT;
+ }
}
} else if (type == CAPTION || type == COL || type == COLGROUP ||
type == FRAME || type == HEAD || type == TBODY ||
@@ -365,9 +429,12 @@ bool process_start_tag(hubbub_treebuilder *treebuilder,
type == THEAD || type == TR) {
/** \todo parse error */
} else {
- process_phrasing_in_body(treebuilder, token);
+ err = process_phrasing_in_body(treebuilder, token);
}
+ if (err == HUBBUB_OK || err == HUBBUB_REPROCESS)
+ treebuilder->context.mode_state = IBS_INITIAL;
+
return err;
}
@@ -378,7 +445,7 @@ bool process_start_tag(hubbub_treebuilder *treebuilder,
* \param token The token to process
* \return True to reprocess the token
*/
-bool process_end_tag(hubbub_treebuilder *treebuilder,
+hubbub_error process_end_tag(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
hubbub_error err = HUBBUB_OK;
@@ -386,18 +453,14 @@ bool process_end_tag(hubbub_treebuilder *treebuilder,
&token->data.tag.name);
if (type == BODY) {
- if (process_0body_in_body(treebuilder) &&
- treebuilder->context.mode == IN_BODY) {
- treebuilder->context.mode = AFTER_BODY;
- }
+ err = process_0body_in_body(treebuilder);
+ /* Never reprocess */
+ if (err == HUBBUB_REPROCESS)
+ err = HUBBUB_OK;
} else if (type == HTML) {
/* Act as if </body> has been seen then, if
* that wasn't ignored, reprocess this token */
- if (process_0body_in_body(treebuilder) &&
- treebuilder->context.mode == IN_BODY) {
- treebuilder->context.mode = AFTER_BODY;
- }
- err = HUBBUB_REPROCESS;
+ err = process_0body_in_body(treebuilder);
} else if (type == ADDRESS || type == ARTICLE || type == ASIDE ||
type == BLOCKQUOTE || type == CENTER || type == DIR ||
type == DATAGRID || type == DIV || type == DL ||
@@ -405,28 +468,28 @@ bool process_end_tag(hubbub_treebuilder *treebuilder,
type == LISTING || type == MENU || type == NAV ||
type == OL || type == PRE || type == SECTION ||
type == UL) {
- process_0container_in_body(treebuilder, type);
+ err = process_0container_in_body(treebuilder, type);
} else if (type == FORM) {
- process_0form_in_body(treebuilder);
+ err = process_0form_in_body(treebuilder);
} else if (type == P) {
- process_0p_in_body(treebuilder);
+ err = process_0p_in_body(treebuilder);
} else if (type == DD || type == DT || type == LI) {
- process_0dd_dt_li_in_body(treebuilder, type);
+ err = process_0dd_dt_li_in_body(treebuilder, type);
} else if (type == H1 || type == H2 || type == H3 ||
type == H4 || type == H5 || type == H6) {
- process_0h_in_body(treebuilder, type);
+ err = process_0h_in_body(treebuilder, type);
} else if (type == A || type == B || type == BIG || type == CODE ||
type == EM || type == FONT || type == I ||
type == NOBR || type == S || type == SMALL ||
type == STRIKE || type == STRONG ||
type == TT || type == U) {
- process_0presentational_in_body(treebuilder, type);
+ err = process_0presentational_in_body(treebuilder, type);
} else if (type == APPLET || type == BUTTON ||
type == MARQUEE || type == OBJECT) {
- process_0applet_button_marquee_object_in_body(
+ err = process_0applet_button_marquee_object_in_body(
treebuilder, type);
} else if (type == BR) {
- process_0br_in_body(treebuilder);
+ err = process_0br_in_body(treebuilder);
} else if (type == AREA || type == BASEFONT ||
type == BGSOUND || type == EMBED ||
type == HR || type == IFRAME ||
@@ -440,9 +503,12 @@ bool process_end_tag(hubbub_treebuilder *treebuilder,
type == NOSCRIPT)) {
/** \todo parse error */
} else {
- process_0generic_in_body(treebuilder, type);
+ err = process_0generic_in_body(treebuilder, type);
}
+ if (err == HUBBUB_OK || err == HUBBUB_REPROCESS)
+ treebuilder->context.mode_state = IBS_INITIAL;
+
return err;
}
@@ -452,12 +518,12 @@ bool process_end_tag(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_html_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_html_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
/** \todo parse error */
- treebuilder->tree_handler->add_attributes(
+ return treebuilder->tree_handler->add_attributes(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[0].node,
token->data.tag.attributes,
@@ -470,16 +536,16 @@ void process_html_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_body_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_body_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
/** \todo parse error */
if (treebuilder->context.current_node < 1 ||
treebuilder->context.element_stack[1].type != BODY)
- return;
+ return HUBBUB_OK;
- treebuilder->tree_handler->add_attributes(
+ return treebuilder->tree_handler->add_attributes(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[1].node,
token->data.tag.attributes,
@@ -492,50 +558,37 @@ void process_body_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_frameset_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_frameset_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
- void *parent = NULL;
+ hubbub_error err = HUBBUB_OK;
/** \todo parse error */
if (treebuilder->context.current_node < 1 ||
treebuilder->context.element_stack[1].type != BODY)
- return;
+ return HUBBUB_OK;
if (treebuilder->context.frameset_ok == false)
- return;
-
- if (treebuilder->tree_handler->get_parent(
- treebuilder->tree_handler->ctx,
- treebuilder->context.element_stack[1].node,
- false, &parent)) {
- /** \todo errors */
- }
+ return HUBBUB_OK;
- if (parent != NULL) {
- void *removed;
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = remove_node_from_dom(treebuilder,
+ treebuilder->context.element_stack[1].node);
+ if (err != HUBBUB_OK)
+ return err;
- if (treebuilder->tree_handler->remove_child(
- treebuilder->tree_handler->ctx,
- parent,
- treebuilder->context.element_stack[1].node,
- &removed)) {
- /** \todo errors */
- }
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, removed);
+ err = element_stack_pop_until(treebuilder, BODY);
+ assert(err == HUBBUB_OK);
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, parent);
+ treebuilder->context.mode_state = IBS_REMOVED_NODE;
}
- if (element_stack_pop_until(treebuilder, BODY) == false) {
- /** \todo errors */
- }
+ err = insert_element(treebuilder, &token->data.tag, true);
+ if (err == HUBBUB_OK)
+ treebuilder->context.mode = IN_FRAMESET;
- insert_element(treebuilder, &token->data.tag, true);
+ return err;
}
/**
@@ -544,14 +597,22 @@ void process_frameset_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_container_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_container_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
- if (element_in_scope(treebuilder, P, false)) {
- process_0p_in_body(treebuilder);
+ hubbub_error err;
+
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ if (element_in_scope(treebuilder, P, false)) {
+ err = process_0p_in_body(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+ }
+
+ treebuilder->context.mode_state = IBS_CLOSED_P;
}
- insert_element(treebuilder, &token->data.tag, true);
+ return insert_element(treebuilder, &token->data.tag, true);
}
/**
@@ -560,36 +621,43 @@ void process_container_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_hN_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_hN_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+ hubbub_error err;
element_type type;
- if (element_in_scope(treebuilder, P, false)) {
- process_0p_in_body(treebuilder);
- }
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ if (element_in_scope(treebuilder, P, false)) {
+ err = process_0p_in_body(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+ }
- type = treebuilder->context.element_stack[
- treebuilder->context.current_node].type;
+ type = treebuilder->context.element_stack[
+ treebuilder->context.current_node].type;
- if (type == H1 || type == H2 || type == H3 || type == H4 ||
- type == H5 || type == H6) {
- hubbub_ns ns;
- element_type otype;
- void *node;
+ if (type == H1 || type == H2 || type == H3 || type == H4 ||
+ type == H5 || type == H6) {
+ hubbub_ns ns;
+ element_type otype;
+ void *node;
- /** \todo parse error */
+ /** \todo parse error */
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
+ err = element_stack_pop(treebuilder,
+ &ns, &otype, &node);
+ assert(err == HUBBUB_OK);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ node);
}
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- node);
+ treebuilder->context.mode_state = IBS_CLOSED_P;
}
- insert_element(treebuilder, &token->data.tag, true);
+ return insert_element(treebuilder, &token->data.tag, true);
}
/**
@@ -598,17 +666,27 @@ void process_hN_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_form_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_form_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+ hubbub_error err;
+
if (treebuilder->context.form_element != NULL) {
/** \todo parse error */
} else {
- if (element_in_scope(treebuilder, P, false)) {
- process_0p_in_body(treebuilder);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ if (element_in_scope(treebuilder, P, false)) {
+ err = process_0p_in_body(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+ }
+
+ treebuilder->context.mode_state = IBS_CLOSED_P;
}
- insert_element(treebuilder, &token->data.tag, true);
+ err = insert_element(treebuilder, &token->data.tag, true);
+ if (err != HUBBUB_OK)
+ return err;
/* Claim a reference on the node and
* use it as the current form element */
@@ -621,6 +699,8 @@ void process_form_in_body(hubbub_treebuilder *treebuilder,
treebuilder->context.element_stack[
treebuilder->context.current_node].node;
}
+
+ return HUBBUB_OK;
}
/**
@@ -630,62 +710,69 @@ void process_form_in_body(hubbub_treebuilder *treebuilder,
* \param token The token to process
* \param type The element type
*/
-void process_dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token, element_type type)
{
+ hubbub_error err;
element_context *stack = treebuilder->context.element_stack;
uint32_t node;
- treebuilder->context.frameset_ok = false;
-
- if (element_in_scope(treebuilder, P, false)) {
- process_0p_in_body(treebuilder);
- }
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ treebuilder->context.frameset_ok = false;
- /* Find last LI/(DD,DT) on stack, if any */
- for (node = treebuilder->context.current_node; node > 0; node--) {
- element_type ntype = stack[node].type;
+ if (element_in_scope(treebuilder, P, false)) {
+ err = process_0p_in_body(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+ }
- if (type == LI && ntype == LI)
- break;
+ /* Find last LI/(DD,DT) on stack, if any */
+ for (node = treebuilder->context.current_node; node > 0;
+ node--) {
+ element_type ntype = stack[node].type;
- if (((type == DD || type == DT) &&
- (ntype == DD || ntype == DT)))
- break;
+ if (type == LI && ntype == LI)
+ break;
- if (!is_formatting_element(ntype) &&
- !is_phrasing_element(ntype) &&
- ntype != ADDRESS &&
- ntype != DIV)
- break;
- }
+ if (((type == DD || type == DT) &&
+ (ntype == DD || ntype == DT)))
+ break;
- /* If we found one, then pop all nodes up to and including it */
- if (stack[node].type == LI || stack[node].type == DD ||
- stack[node].type == DT) {
- /* Check that we're only popping one node
- * and emit a parse error if not */
- if (treebuilder->context.current_node > node) {
- /** \todo parse error */
+ if (!is_formatting_element(ntype) &&
+ !is_phrasing_element(ntype) &&
+ ntype != ADDRESS &&
+ ntype != DIV)
+ break;
}
- do {
- hubbub_ns ns;
- element_type otype;
- void *node;
-
- if (!element_stack_pop(treebuilder, &ns,
- &otype, &node)) {
- /** \todo errors */
+ /* If we found one, then pop all nodes up to and including it */
+ if (stack[node].type == LI || stack[node].type == DD ||
+ stack[node].type == DT) {
+ /* Check that we're only popping one node
+ * and emit a parse error if not */
+ if (treebuilder->context.current_node > node) {
+ /** \todo parse error */
}
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- node);
- } while (treebuilder->context.current_node >= node);
+ do {
+ hubbub_ns ns;
+ element_type otype;
+ void *node;
+
+ err = element_stack_pop(treebuilder, &ns,
+ &otype, &node);
+ assert(err == HUBBUB_OK);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ node);
+ } while (treebuilder->context.current_node >= node);
+ }
+
+ treebuilder->context.mode_state = IBS_CLOSED_P;
}
- insert_element(treebuilder, &token->data.tag, true);
+ return insert_element(treebuilder, &token->data.tag, true);
}
/**
@@ -694,22 +781,34 @@ void process_dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_plaintext_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_plaintext_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+ hubbub_error err;
hubbub_tokeniser_optparams params;
- if (element_in_scope(treebuilder, P, false)) {
- process_0p_in_body(treebuilder);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ if (element_in_scope(treebuilder, P, false)) {
+ err = process_0p_in_body(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+ }
+
+ treebuilder->context.mode_state = IBS_CLOSED_P;
}
- insert_element(treebuilder, &token->data.tag, true);
+ err = insert_element(treebuilder, &token->data.tag, true);
+ if (err != HUBBUB_OK)
+ return err;
params.content_model.model = HUBBUB_CONTENT_MODEL_PLAINTEXT;
- hubbub_tokeniser_setopt(treebuilder->tokeniser,
+ err = hubbub_tokeniser_setopt(treebuilder->tokeniser,
HUBBUB_TOKENISER_CONTENT_MODEL,
&params);
+ assert(err == HUBBUB_OK);
+
+ return HUBBUB_OK;
}
/**
@@ -718,9 +817,10 @@ void process_plaintext_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_a_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_a_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+/** \todo error recovery */
formatting_list_entry *entry =
aa_find_formatting_element(treebuilder, A);
@@ -779,6 +879,8 @@ void process_a_in_body(hubbub_treebuilder *treebuilder,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
treebuilder->context.current_node);
+
+ return HUBBUB_OK;
}
/**
@@ -789,21 +891,56 @@ void process_a_in_body(hubbub_treebuilder *treebuilder,
* \param token The token to process
* \param type The element type
*/
-void process_presentational_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_presentational_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token, element_type type)
{
- reconstruct_active_formatting_list(treebuilder);
+ hubbub_error err;
- insert_element(treebuilder, &token->data.tag, true);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->context.mode_state = IBS_DONE_FORMATTING_LIST;
+ }
+
+ err = insert_element(treebuilder, &token->data.tag, true);
+ if (err != HUBBUB_OK)
+ return err;
treebuilder->tree_handler->ref_node(treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
- formatting_list_append(treebuilder, token->data.tag.ns, type,
+ err = formatting_list_append(treebuilder, token->data.tag.ns, type,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
treebuilder->context.current_node);
+ if (err != HUBBUB_OK) {
+ hubbub_error e;
+ hubbub_ns ns;
+ element_type type;
+ void *node;
+
+ e = remove_node_from_dom(treebuilder,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ assert(e == HUBBUB_OK);
+
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
+
+ /* Unref twice (once for stack, once for formatting list) */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, node);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, node);
+
+ return err;
+ }
+
+ return HUBBUB_OK;
}
/**
@@ -812,9 +949,10 @@ void process_presentational_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_nobr_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_nobr_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+/** \todo error recovery */
reconstruct_active_formatting_list(treebuilder);
if (element_in_scope(treebuilder, NOBR, false)) {
@@ -838,6 +976,8 @@ void process_nobr_in_body(hubbub_treebuilder *treebuilder,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
treebuilder->context.current_node);
+
+ return HUBBUB_OK;
}
/**
@@ -846,32 +986,68 @@ void process_nobr_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_button_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_button_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
- if (element_in_scope(treebuilder, BUTTON, false)) {
- /** \todo parse error */
+ hubbub_error err;
- /* Act as if </button> has been seen */
- process_0applet_button_marquee_object_in_body(treebuilder,
- BUTTON);
- }
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ if (element_in_scope(treebuilder, BUTTON, false)) {
+ /** \todo parse error */
- reconstruct_active_formatting_list(treebuilder);
+ /* Act as if </button> has been seen */
+ err = process_0applet_button_marquee_object_in_body(
+ treebuilder, BUTTON);
+ assert(err == HUBBUB_OK);
+ }
- insert_element(treebuilder, &token->data.tag, true);
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->context.mode_state = IBS_DONE_FORMATTING_LIST;
+ }
+
+ err = insert_element(treebuilder, &token->data.tag, true);
+ if (err != HUBBUB_OK)
+ return err;
treebuilder->tree_handler->ref_node(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
- formatting_list_append(treebuilder, token->data.tag.ns, BUTTON,
+ err = formatting_list_append(treebuilder, token->data.tag.ns, BUTTON,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
treebuilder->context.current_node);
+ if (err != HUBBUB_OK) {
+ hubbub_error e;
+ hubbub_ns ns;
+ element_type type;
+ void *node;
+
+ e = remove_node_from_dom(treebuilder,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ assert(e == HUBBUB_OK);
+
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
+
+ /* Unref twice (once for stack, once for formatting list) */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, node);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, node);
+
+ return err;
+ }
treebuilder->context.frameset_ok = false;
+
+ return HUBBUB_OK;
}
/**
@@ -881,24 +1057,60 @@ void process_button_in_body(hubbub_treebuilder *treebuilder,
* \param token The token to process
* \param type The element type
*/
-void process_applet_marquee_object_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_applet_marquee_object_in_body(
+ hubbub_treebuilder *treebuilder,
const hubbub_token *token, element_type type)
{
- reconstruct_active_formatting_list(treebuilder);
+ hubbub_error err;
- insert_element(treebuilder, &token->data.tag, true);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->context.mode_state = IBS_DONE_FORMATTING_LIST;
+ }
+
+ err = insert_element(treebuilder, &token->data.tag, true);
+ if (err != HUBBUB_OK)
+ return err;
treebuilder->tree_handler->ref_node(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
- formatting_list_append(treebuilder, token->data.tag.ns, type,
+ err = formatting_list_append(treebuilder, token->data.tag.ns, type,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
treebuilder->context.current_node);
+ if (err != HUBBUB_OK) {
+ hubbub_error e;
+ hubbub_ns ns;
+ element_type type;
+ void *node;
+
+ e = remove_node_from_dom(treebuilder,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ assert(e == HUBBUB_OK);
+
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
+
+ /* Unref twice (once for stack, once for formatting list) */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, node);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, node);
+
+ return err;
+ }
treebuilder->context.frameset_ok = false;
+
+ return HUBBUB_OK;
}
/**
@@ -907,16 +1119,26 @@ void process_applet_marquee_object_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_hr_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_hr_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
- if (element_in_scope(treebuilder, P, false)) {
- process_0p_in_body(treebuilder);
+ hubbub_error err;
+
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ if (element_in_scope(treebuilder, P, false)) {
+ err = process_0p_in_body(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+ }
+
+ treebuilder->context.mode_state = IBS_CLOSED_P;
}
- insert_element(treebuilder, &token->data.tag, false);
+ err = insert_element(treebuilder, &token->data.tag, false);
+ if (err == HUBBUB_OK)
+ treebuilder->context.frameset_ok = false;
- treebuilder->context.frameset_ok = false;
+ return err;
}
/**
@@ -925,9 +1147,10 @@ void process_hr_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_image_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_image_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+ hubbub_error err;
hubbub_tag tag;
tag.ns = HUBBUB_NS_HTML;
@@ -937,9 +1160,15 @@ void process_image_in_body(hubbub_treebuilder *treebuilder,
tag.n_attributes = token->data.tag.n_attributes;
tag.attributes = token->data.tag.attributes;
- reconstruct_active_formatting_list(treebuilder);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->context.mode_state = IBS_DONE_FORMATTING_LIST;
+ }
- insert_element(treebuilder, &tag, false);
+ return insert_element(treebuilder, &tag, false);
}
/**
@@ -948,9 +1177,10 @@ void process_image_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_isindex_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_isindex_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+/** \todo error recovery */
hubbub_token dummy;
hubbub_attribute *action = NULL;
hubbub_attribute *prompt = NULL;
@@ -960,7 +1190,7 @@ void process_isindex_in_body(hubbub_treebuilder *treebuilder,
/** \todo parse error */
if (treebuilder->context.form_element != NULL)
- return;
+ return HUBBUB_OK;
/* First up, clone the token's attributes */
if (token->data.tag.n_attributes > 0) {
@@ -969,10 +1199,8 @@ void process_isindex_in_body(hubbub_treebuilder *treebuilder,
(token->data.tag.n_attributes + 1) *
sizeof(hubbub_attribute),
treebuilder->alloc_pw);
- if (attrs == NULL) {
- /** \todo error handling */
- return;
- }
+ if (attrs == NULL)
+ return HUBBUB_NOMEM;
for (i = 0; i < token->data.tag.n_attributes; i++) {
hubbub_attribute *attr = &token->data.tag.attributes[i];
@@ -1084,6 +1312,8 @@ void process_isindex_in_body(hubbub_treebuilder *treebuilder,
/* Clean up */
treebuilder->alloc(attrs, 0, treebuilder->alloc_pw);
+
+ return HUBBUB_OK;
}
/**
@@ -1092,12 +1322,12 @@ void process_isindex_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_textarea_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_textarea_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
treebuilder->context.strip_leading_lr = true;
treebuilder->context.frameset_ok = false;
- parse_generic_rcdata(treebuilder, token, true);
+ return parse_generic_rcdata(treebuilder, token, true);
}
/**
@@ -1106,14 +1336,24 @@ void process_textarea_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_select_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_select_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
- reconstruct_active_formatting_list(treebuilder);
+ hubbub_error err;
- insert_element(treebuilder, &token->data.tag, true);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
- treebuilder->context.frameset_ok = false;
+ treebuilder->context.mode_state = IBS_DONE_FORMATTING_LIST;
+ }
+
+ err = insert_element(treebuilder, &token->data.tag, true);
+ if (err == HUBBUB_OK)
+ treebuilder->context.frameset_ok = false;
+
+ return err;
}
/**
@@ -1122,16 +1362,26 @@ void process_select_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_opt_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_opt_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
- if (element_in_scope(treebuilder, OPTION, false)) {
- process_0generic_in_body(treebuilder, OPTION);
- }
+ hubbub_error err;
+
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ if (element_in_scope(treebuilder, OPTION, false)) {
+ err = process_0generic_in_body(treebuilder, OPTION);
+ /* Cannot fail */
+ assert(err == HUBBUB_OK);
+ }
- reconstruct_active_formatting_list(treebuilder);
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
- insert_element(treebuilder, &token->data.tag, true);
+ treebuilder->context.mode_state = IBS_DONE_FORMATTING_LIST;
+ }
+
+ return insert_element(treebuilder, &token->data.tag, true);
}
/**
@@ -1140,12 +1390,18 @@ void process_opt_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The token to process
*/
-void process_phrasing_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_phrasing_in_body(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
- reconstruct_active_formatting_list(treebuilder);
+ hubbub_error err;
- insert_element(treebuilder, &token->data.tag, true);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
+ }
+
+ return insert_element(treebuilder, &token->data.tag, true);
}
/**
@@ -1154,13 +1410,12 @@ void process_phrasing_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \return True if processed, false otherwise
*/
-bool process_0body_in_body(hubbub_treebuilder *treebuilder)
+hubbub_error process_0body_in_body(hubbub_treebuilder *treebuilder)
{
- bool processed = true;
+ hubbub_error err = HUBBUB_OK;
if (!element_in_scope(treebuilder, BODY, false)) {
/** \todo parse error */
- processed = true;
} else {
element_context *stack = treebuilder->context.element_stack;
uint32_t node;
@@ -1179,9 +1434,14 @@ bool process_0body_in_body(hubbub_treebuilder *treebuilder)
/** \todo parse error */
}
}
+
+ if (treebuilder->context.mode == IN_BODY)
+ treebuilder->context.mode = AFTER_BODY;
+
+ err = HUBBUB_REPROCESS;
}
- return processed;
+ return err;
}
/**
@@ -1190,7 +1450,7 @@ bool process_0body_in_body(hubbub_treebuilder *treebuilder)
* \param treebuilder The treebuilder instance
* \param type The element type
*/
-void process_0container_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_0container_in_body(hubbub_treebuilder *treebuilder,
element_type type)
{
if (!element_in_scope(treebuilder, type, false)) {
@@ -1202,13 +1462,12 @@ void process_0container_in_body(hubbub_treebuilder *treebuilder,
close_implied_end_tags(treebuilder, UNKNOWN);
do {
+ hubbub_error e;
hubbub_ns ns;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -1221,6 +1480,8 @@ void process_0container_in_body(hubbub_treebuilder *treebuilder,
/** \todo parse error */
}
}
+
+ return HUBBUB_OK;
}
/**
@@ -1228,8 +1489,9 @@ void process_0container_in_body(hubbub_treebuilder *treebuilder,
*
* \param treebuilder The treebuilder instance
*/
-void process_0form_in_body(hubbub_treebuilder *treebuilder)
+hubbub_error process_0form_in_body(hubbub_treebuilder *treebuilder)
{
+ hubbub_error err;
void *node = treebuilder->context.form_element;
uint32_t idx = 0;
@@ -1257,12 +1519,16 @@ void process_0form_in_body(hubbub_treebuilder *treebuilder)
/** \todo parse error */
}
- element_stack_remove(treebuilder, idx, &ns, &otype, &node);
+ err = element_stack_remove(treebuilder, idx,
+ &ns, &otype, &node);
+ assert(err == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
node);
}
+
+ return HUBBUB_OK;
}
@@ -1271,8 +1537,9 @@ void process_0form_in_body(hubbub_treebuilder *treebuilder)
*
* \param treebuilder The treebuilder instance
*/
-void process_0p_in_body(hubbub_treebuilder *treebuilder)
+hubbub_error process_0p_in_body(hubbub_treebuilder *treebuilder)
{
+ hubbub_error err = HUBBUB_OK;
uint32_t popped = 0;
if (treebuilder->context.element_stack[
@@ -1285,9 +1552,8 @@ void process_0p_in_body(hubbub_treebuilder *treebuilder)
element_type type;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &type, &node)) {
- /** \todo errors */
- }
+ err = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(err == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx, node);
@@ -1305,12 +1571,18 @@ void process_0p_in_body(hubbub_treebuilder *treebuilder)
dummy.data.tag.n_attributes = 0;
dummy.data.tag.attributes = NULL;
- process_container_in_body(treebuilder, &dummy);
+ err = process_container_in_body(treebuilder, &dummy);
+ if (err != HUBBUB_OK)
+ return err;
/* Reprocess the end tag. This is safe as we've just
* inserted a <p> into the current scope */
- process_0p_in_body(treebuilder);
+ err = process_0p_in_body(treebuilder);
+ /* Cannot fail */
+ assert(err == HUBBUB_OK);
}
+
+ return err;
}
/**
@@ -1319,9 +1591,11 @@ void process_0p_in_body(hubbub_treebuilder *treebuilder)
* \param treebuilder The treebuilder instance
* \param type The element type
*/
-void process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
element_type type)
{
+ hubbub_error err;
+
if (!element_in_scope(treebuilder, type, false)) {
/** \todo parse error */
} else {
@@ -1334,9 +1608,9 @@ void process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
hubbub_ns ns;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+ err = element_stack_pop(treebuilder,
+ &ns, &otype, &node);
+ assert(err == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -1349,6 +1623,8 @@ void process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
/** \todo parse error */
}
}
+
+ return HUBBUB_OK;
}
/**
@@ -1357,7 +1633,7 @@ void process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param type The element type
*/
-void process_0h_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_0h_in_body(hubbub_treebuilder *treebuilder,
element_type type)
{
UNUSED(type);
@@ -1375,13 +1651,12 @@ void process_0h_in_body(hubbub_treebuilder *treebuilder,
close_implied_end_tags(treebuilder, UNKNOWN);
do {
+ hubbub_error e;
hubbub_ns ns;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -1398,6 +1673,8 @@ void process_0h_in_body(hubbub_treebuilder *treebuilder,
} else {
/** \todo parse error */
}
+
+ return HUBBUB_OK;
}
/**
@@ -1406,9 +1683,12 @@ void process_0h_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param type The element type
*/
-void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_0presentational_in_body(hubbub_treebuilder *treebuilder,
element_type type)
{
+ hubbub_error err;
+
+/** \todo error recovery */
/* Welcome to the adoption agency */
while (true) {
@@ -1429,9 +1709,11 @@ void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
uint32_t oindex;
/* 1 */
- if (!aa_find_and_validate_formatting_element(treebuilder,
- type, &entry))
- return;
+ err = aa_find_and_validate_formatting_element(treebuilder,
+ type, &entry);
+ assert(err == HUBBUB_OK || err == HUBBUB_REPROCESS);
+ if (err == HUBBUB_OK)
+ return err;
assert(entry->details.type == type);
@@ -1440,9 +1722,11 @@ void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
formatting_element = entry->stack_index;
/* 2 & 3 */
- if (!aa_find_furthest_block(treebuilder,
- entry, &furthest_block))
- return;
+ err = aa_find_furthest_block(treebuilder,
+ entry, &furthest_block);
+ assert(err == HUBBUB_OK || err == HUBBUB_REPROCESS);
+ if (err == HUBBUB_OK)
+ return err;
/* 4 */
common_ancestor = formatting_element - 1;
@@ -1452,9 +1736,11 @@ void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
bookmark.next = entry->next;
/* 6 */
- aa_find_bookmark_location_reparenting_misnested(treebuilder,
- formatting_element, &furthest_block,
- &bookmark, &last_node);
+ err = aa_find_bookmark_location_reparenting_misnested(
+ treebuilder, formatting_element,
+ &furthest_block, &bookmark, &last_node);
+ if (err != HUBBUB_OK)
+ return err;
/* 7 */
if (stack[common_ancestor].type == TABLE ||
@@ -1462,13 +1748,21 @@ void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
stack[common_ancestor].type == TFOOT ||
stack[common_ancestor].type == THEAD ||
stack[common_ancestor].type == TR) {
- reparented = aa_insert_into_foster_parent(treebuilder,
- stack[last_node].node);
+ err = aa_insert_into_foster_parent(treebuilder,
+ stack[last_node].node, &reparented);
} else {
- reparented = aa_reparent_node(treebuilder,
+ err = aa_reparent_node(treebuilder,
stack[last_node].node,
- stack[common_ancestor].node);
+ stack[common_ancestor].node,
+ &reparented);
}
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ stack[last_node].node);
+
/* If the reparented node is not the same as the one we were
* previously using, then have it take the place of the other
* one in the formatting list and stack. */
@@ -1494,20 +1788,26 @@ void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
}
/* 8 */
- treebuilder->tree_handler->clone_node(
+ err = treebuilder->tree_handler->clone_node(
treebuilder->tree_handler->ctx,
entry->details.node, false, &fe_clone);
+ if (err != HUBBUB_OK)
+ return err;
/* 9 */
- treebuilder->tree_handler->reparent_children(
+ err = treebuilder->tree_handler->reparent_children(
treebuilder->tree_handler->ctx,
stack[furthest_block].node, fe_clone);
+ if (err != HUBBUB_OK)
+ return err;
/* 10 */
- treebuilder->tree_handler->append_child(
+ err = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
stack[furthest_block].node, fe_clone,
&clone_appended);
+ if (err != HUBBUB_OK)
+ return err;
if (clone_appended != fe_clone) {
/* No longer interested in fe_clone */
@@ -1525,8 +1825,9 @@ void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
* stack index to use when inserting into the formatting list */
/* 12 */
- aa_remove_element_stack_item(treebuilder, formatting_element,
- furthest_block);
+ err = aa_remove_element_stack_item(treebuilder,
+ formatting_element, furthest_block);
+ assert(err == HUBBUB_OK);
/* Fix up furthest block index */
furthest_block--;
@@ -1537,15 +1838,18 @@ void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
stack[furthest_block + 1].node = clone_appended;
/* 11 */
- formatting_list_remove(treebuilder, entry,
+ err = formatting_list_remove(treebuilder, entry,
&ons, &otype, &onode, &oindex);
+ assert(err == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx, onode);
- formatting_list_insert(treebuilder,
+ err = formatting_list_insert(treebuilder,
bookmark.prev, bookmark.next,
ons, otype, clone_appended, furthest_block + 1);
+ if (err != HUBBUB_OK)
+ return err;
/* 13 */
}
@@ -1557,9 +1861,11 @@ void process_0presentational_in_body(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param type Element type to search for
* \param element Pointer to location to receive list entry
- * \return True to continue processing, false to stop
+ * \return HUBBUB_REPROCESS to continue processing,
+ * HUBBUB_OK to stop.
*/
-bool aa_find_and_validate_formatting_element(hubbub_treebuilder *treebuilder,
+hubbub_error aa_find_and_validate_formatting_element(
+ hubbub_treebuilder *treebuilder,
element_type type, formatting_list_entry **element)
{
formatting_list_entry *entry;
@@ -1570,11 +1876,12 @@ bool aa_find_and_validate_formatting_element(hubbub_treebuilder *treebuilder,
element_in_scope(treebuilder, entry->details.type,
false) != entry->stack_index)) {
/** \todo parse error */
- return false;
+ return HUBBUB_OK;
}
if (entry->stack_index == 0) {
/* Not in element stack => remove from formatting list */
+ hubbub_error e;
hubbub_ns ns;
element_type type;
void *node;
@@ -1582,15 +1889,14 @@ bool aa_find_and_validate_formatting_element(hubbub_treebuilder *treebuilder,
/** \todo parse error */
- if (!formatting_list_remove(treebuilder, entry,
- &ns, &type, &node, &index)) {
- /** \todo errors */
- }
+ e = formatting_list_remove(treebuilder, entry,
+ &ns, &type, &node, &index);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx, node);
- return false;
+ return HUBBUB_OK;
}
if (entry->stack_index != treebuilder->context.current_node) {
@@ -1599,7 +1905,7 @@ bool aa_find_and_validate_formatting_element(hubbub_treebuilder *treebuilder,
*element = entry;
- return true;
+ return HUBBUB_REPROCESS;
}
/**
@@ -1636,9 +1942,10 @@ formatting_list_entry *aa_find_formatting_element(
* \param treebuilder The treebuilder instance
* \param formatting_element The formatting element
* \param furthest_block Pointer to location to receive furthest block
- * \return True to continue processing (::furthest_block filled in).
+ * \return HUBBUB_REPROCESS to continue processing (::furthest_block filled in),
+ * HUBBUB_OK to stop.
*/
-bool aa_find_furthest_block(hubbub_treebuilder *treebuilder,
+hubbub_error aa_find_furthest_block(hubbub_treebuilder *treebuilder,
formatting_list_entry *formatting_element,
uint32_t *furthest_block)
{
@@ -1653,6 +1960,7 @@ bool aa_find_furthest_block(hubbub_treebuilder *treebuilder,
}
if (fb > treebuilder->context.current_node) {
+ hubbub_error e;
hubbub_ns ns;
element_type type;
void *node;
@@ -1661,9 +1969,8 @@ bool aa_find_furthest_block(hubbub_treebuilder *treebuilder,
/* Pop all elements off the stack up to,
* and including, the formatting element */
do {
- if (!element_stack_pop(treebuilder, &ns, &type, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -1671,49 +1978,19 @@ bool aa_find_furthest_block(hubbub_treebuilder *treebuilder,
} while (treebuilder->context.current_node >= fe_index);
/* Remove the formatting element from the list */
- if (!formatting_list_remove(treebuilder, formatting_element,
- &ns, &type, &node, &index)) {
- /* \todo errors */
- }
+ e = formatting_list_remove(treebuilder, formatting_element,
+ &ns, &type, &node, &index);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx, node);
- return false;
+ return HUBBUB_OK;
}
*furthest_block = fb;
- return true;
-}
-
-/**
- * Adoption agency: remove a node from its parent
- *
- * \param treebuilder The treebuilder instance
- * \param node Node to remove
- */
-void aa_remove_from_parent(hubbub_treebuilder *treebuilder, void *node)
-{
- /* Get parent */
- void *parent = NULL;
-
- treebuilder->tree_handler->get_parent(treebuilder->tree_handler->ctx,
- node, false, &parent);
-
- if (parent != NULL) {
- void *removed;
-
- treebuilder->tree_handler->remove_child(
- treebuilder->tree_handler->ctx,
- parent, node, &removed);
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, removed);
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, parent);
- }
+ return HUBBUB_REPROCESS;
}
/**
@@ -1722,26 +1999,25 @@ void aa_remove_from_parent(hubbub_treebuilder *treebuilder, void *node)
* \param treebuilder The treebuilder instance
* \param node The node to reparent
* \param new_parent The new parent
- * \return Pointer to reparented node
+ * \param reparented Pointer to location to receive reparented node
+ * \return HUBBUB_OK on success, appropriate error otherwise
*/
-void *aa_reparent_node(hubbub_treebuilder *treebuilder, void *node,
- void *new_parent)
+hubbub_error aa_reparent_node(hubbub_treebuilder *treebuilder, void *node,
+ void *new_parent, void **reparented)
{
- void *appended;
+ hubbub_error err;
- aa_remove_from_parent(treebuilder, node);
+ err = remove_node_from_dom(treebuilder, node);
+ if (err != HUBBUB_OK)
+ return err;
- treebuilder->tree_handler->append_child(treebuilder->tree_handler->ctx,
- new_parent, node, &appended);
-
- treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx,
- node);
-
- return appended;
+ return treebuilder->tree_handler->append_child(
+ treebuilder->tree_handler->ctx,
+ new_parent, node, reparented);
}
/**
- * Adoption agency: this is step 7
+ * Adoption agency: this is step 6
*
* \param treebuilder The treebuilder instance
* \param formatting_element The stack index of the formatting element
@@ -1750,11 +2026,12 @@ void *aa_reparent_node(hubbub_treebuilder *treebuilder, void *node,
* \param bookmark Pointer to bookmark (pre-initialised)
* \param last_node Pointer to location to receive index of last node
*/
-void aa_find_bookmark_location_reparenting_misnested(
+hubbub_error aa_find_bookmark_location_reparenting_misnested(
hubbub_treebuilder *treebuilder,
uint32_t formatting_element, uint32_t *furthest_block,
bookmark *bookmark, uint32_t *last_node)
{
+ hubbub_error err;
element_context *stack = treebuilder->context.element_stack;
uint32_t node, last, fb;
formatting_list_entry *node_entry;
@@ -1777,8 +2054,9 @@ void aa_find_bookmark_location_reparenting_misnested(
/* Node is not in list of active formatting elements */
if (node_entry == NULL) {
- aa_remove_element_stack_item(treebuilder,
+ err = aa_remove_element_stack_item(treebuilder,
node, treebuilder->context.current_node);
+ assert(err == HUBBUB_OK);
/* Update furthest block index and the last node index,
* as these are always below node in the stack */
@@ -1803,11 +2081,22 @@ void aa_find_bookmark_location_reparenting_misnested(
}
/* v */
- aa_clone_and_replace_entries(treebuilder, node_entry);
+ err = aa_clone_and_replace_entries(treebuilder, node_entry);
+ if (err != HUBBUB_OK) {
+ /** \todo error recovery */
+ return err;
+ }
/* vi */
- reparented = aa_reparent_node(treebuilder,
- stack[last].node, stack[node].node);
+ err = aa_reparent_node(treebuilder, stack[last].node,
+ stack[node].node, &reparented);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ stack[last].node);
+
/* If the reparented node is not the same as the one we were
* previously using, then have it take the place of the other
* one in the formatting list and stack. */
@@ -1840,6 +2129,8 @@ void aa_find_bookmark_location_reparenting_misnested(
*furthest_block = fb;
*last_node = last;
+
+ return HUBBUB_OK;
}
/**
@@ -1852,7 +2143,7 @@ void aa_find_bookmark_location_reparenting_misnested(
* Preconditions: index < limit, limit <= current_node
* Postcondition: stack[limit] is empty
*/
-void aa_remove_element_stack_item(hubbub_treebuilder *treebuilder,
+hubbub_error aa_remove_element_stack_item(hubbub_treebuilder *treebuilder,
uint32_t index, uint32_t limit)
{
element_context *stack = treebuilder->context.element_stack;
@@ -1888,6 +2179,8 @@ void aa_remove_element_stack_item(hubbub_treebuilder *treebuilder,
/* Now, shuffle the stack up one, removing node in the process */
memmove(&stack[index], &stack[index + 1],
(limit - index) * sizeof(element_context));
+
+ return HUBBUB_OK;
}
/**
@@ -1897,23 +2190,28 @@ void aa_remove_element_stack_item(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param element The item in the formatting list containing the node
*/
-void aa_clone_and_replace_entries(hubbub_treebuilder *treebuilder,
+hubbub_error aa_clone_and_replace_entries(hubbub_treebuilder *treebuilder,
formatting_list_entry *element)
{
+ hubbub_error err;
hubbub_ns ons;
element_type otype;
uint32_t oindex;
void *clone, *onode;
/* Shallow clone of node */
- treebuilder->tree_handler->clone_node(treebuilder->tree_handler->ctx,
+ err = treebuilder->tree_handler->clone_node(
+ treebuilder->tree_handler->ctx,
element->details.node, false, &clone);
+ if (err != HUBBUB_OK)
+ return err;
/* Replace formatting list entry for node with clone */
- formatting_list_replace(treebuilder, element,
+ err = formatting_list_replace(treebuilder, element,
element->details.ns, element->details.type,
clone, element->stack_index,
&ons, &otype, &onode, &oindex);
+ assert(err == HUBBUB_OK);
treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx,
onode);
@@ -1926,6 +2224,8 @@ void aa_clone_and_replace_entries(hubbub_treebuilder *treebuilder,
treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx,
onode);
+
+ return HUBBUB_OK;
}
/**
@@ -1933,14 +2233,16 @@ void aa_clone_and_replace_entries(hubbub_treebuilder *treebuilder,
*
* \param treebuilder The treebuilder instance
* \param node The node to insert
- * \return Pointer to inserted node
+ * \param inserted Pointer to location to receive inserted node
+ * \return HUBBUB_OK on success, appropriate error otherwise
*/
-void *aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder, void *node)
+hubbub_error aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder,
+ void *node, void **inserted)
{
+ hubbub_error err;
element_context *stack = treebuilder->context.element_stack;
void *foster_parent = NULL;
bool insert = false;
- void *inserted;
uint32_t cur_table = current_table(treebuilder);
@@ -1971,28 +2273,29 @@ void *aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder, void *node)
}
}
- aa_remove_from_parent(treebuilder, node);
+ err = remove_node_from_dom(treebuilder, node);
+ if (err != HUBBUB_OK)
+ return err;
if (insert) {
- treebuilder->tree_handler->insert_before(
+ err = treebuilder->tree_handler->insert_before(
treebuilder->tree_handler->ctx,
foster_parent, node,
stack[cur_table].node,
- &inserted);
+ inserted);
} else {
- treebuilder->tree_handler->append_child(
+ err = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
foster_parent, node,
- &inserted);
+ inserted);
}
-
- treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx,
- node);
+ if (err != HUBBUB_OK)
+ return err;
treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx,
foster_parent);
- return inserted;
+ return HUBBUB_OK;
}
@@ -2002,7 +2305,7 @@ void *aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder, void *node)
* \param treebuilder The treebuilder instance
* \param type The element type
*/
-void process_0applet_button_marquee_object_in_body(
+hubbub_error process_0applet_button_marquee_object_in_body(
hubbub_treebuilder *treebuilder, element_type type)
{
if (!element_in_scope(treebuilder, type, false)) {
@@ -2014,13 +2317,12 @@ void process_0applet_button_marquee_object_in_body(
close_implied_end_tags(treebuilder, UNKNOWN);
do {
+ hubbub_error e;
hubbub_ns ns;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -2035,6 +2337,8 @@ void process_0applet_button_marquee_object_in_body(
clear_active_formatting_list_to_marker(treebuilder);
}
+
+ return HUBBUB_OK;
}
/**
@@ -2042,8 +2346,9 @@ void process_0applet_button_marquee_object_in_body(
*
* \param treebuilder The treebuilder instance
*/
-void process_0br_in_body(hubbub_treebuilder *treebuilder)
+hubbub_error process_0br_in_body(hubbub_treebuilder *treebuilder)
{
+ hubbub_error err;
hubbub_tag tag;
/** \todo parse error */
@@ -2057,9 +2362,15 @@ void process_0br_in_body(hubbub_treebuilder *treebuilder)
tag.n_attributes = 0;
tag.attributes = NULL;
- reconstruct_active_formatting_list(treebuilder);
+ if (treebuilder->context.mode_state == IBS_INITIAL) {
+ err = reconstruct_active_formatting_list(treebuilder);
+ if (err != HUBBUB_OK)
+ return err;
- insert_element(treebuilder, &tag, false);
+ treebuilder->context.mode_state = IBS_DONE_FORMATTING_LIST;
+ }
+
+ return insert_element(treebuilder, &tag, false);
}
/**
@@ -2068,7 +2379,7 @@ void process_0br_in_body(hubbub_treebuilder *treebuilder)
* \param treebuilder The treebuilder instance
* \param type The element type
*/
-void process_0generic_in_body(hubbub_treebuilder *treebuilder,
+hubbub_error process_0generic_in_body(hubbub_treebuilder *treebuilder,
element_type type)
{
element_context *stack = treebuilder->context.element_stack;
@@ -2082,13 +2393,13 @@ void process_0generic_in_body(hubbub_treebuilder *treebuilder,
close_implied_end_tags(treebuilder, UNKNOWN);
while (treebuilder->context.current_node >= node) {
+ hubbub_error e;
hubbub_ns ns;
void *node;
- if (!element_stack_pop(treebuilder,
- &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder,
+ &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -2111,5 +2422,7 @@ void process_0generic_in_body(hubbub_treebuilder *treebuilder,
break;
}
} while (--node > 0);
+
+ return HUBBUB_OK;
}
diff --git a/src/treebuilder/in_caption.c b/src/treebuilder/in_caption.c
index 6e6eb6a..24f30e4 100644
--- a/src/treebuilder/in_caption.c
+++ b/src/treebuilder/in_caption.c
@@ -40,7 +40,7 @@ hubbub_error handle_in_caption(hubbub_treebuilder *treebuilder,
err = HUBBUB_REPROCESS;
} else {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
}
}
break;
@@ -61,7 +61,7 @@ hubbub_error handle_in_caption(hubbub_treebuilder *treebuilder,
/** \todo parse error */
} else {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
}
}
break;
@@ -70,12 +70,13 @@ hubbub_error handle_in_caption(hubbub_treebuilder *treebuilder,
case HUBBUB_TOKEN_DOCTYPE:
case HUBBUB_TOKEN_EOF:
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
break;
}
if (handled || err == HUBBUB_REPROCESS) {
+ hubbub_error e;
hubbub_ns ns;
element_type otype = UNKNOWN;
void *node;
@@ -84,14 +85,11 @@ hubbub_error handle_in_caption(hubbub_treebuilder *treebuilder,
close_implied_end_tags(treebuilder, UNKNOWN);
-
while (otype != CAPTION) {
/** \todo parse error */
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
diff --git a/src/treebuilder/in_cell.c b/src/treebuilder/in_cell.c
index 6a6c918..0510126 100644
--- a/src/treebuilder/in_cell.c
+++ b/src/treebuilder/in_cell.c
@@ -21,6 +21,7 @@
*/
static inline void close_cell(hubbub_treebuilder *treebuilder)
{
+ hubbub_error e;
hubbub_ns ns;
element_type otype = UNKNOWN;
void *node;
@@ -39,9 +40,8 @@ static inline void close_cell(hubbub_treebuilder *treebuilder)
/** \todo parse error */
while (otype != type) {
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -62,7 +62,8 @@ static inline void close_cell(hubbub_treebuilder *treebuilder)
* \param token The token to process
* \return True to reprocess the token, false otherwise
*/
-hubbub_error handle_in_cell(hubbub_treebuilder *treebuilder, const hubbub_token *token)
+hubbub_error handle_in_cell(hubbub_treebuilder *treebuilder,
+ const hubbub_token *token)
{
hubbub_error err = HUBBUB_OK;
@@ -91,6 +92,7 @@ hubbub_error handle_in_cell(hubbub_treebuilder *treebuilder, const hubbub_token
if (type == TH || type == TD) {
if (element_in_scope(treebuilder, type, true)) {
+ hubbub_error e;
hubbub_ns ns;
element_type otype = UNKNOWN;
void *node;
@@ -99,14 +101,13 @@ hubbub_error handle_in_cell(hubbub_treebuilder *treebuilder, const hubbub_token
/** \todo parse error */
while (otype != type) {
- if (!element_stack_pop(treebuilder,
- &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder,
+ &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- node);
+ treebuilder->tree_handler->ctx,
+ node);
}
clear_active_formatting_list_to_marker(
diff --git a/src/treebuilder/in_column_group.c b/src/treebuilder/in_column_group.c
index e489e6b..ba0a4e1 100644
--- a/src/treebuilder/in_column_group.c
+++ b/src/treebuilder/in_column_group.c
@@ -29,13 +29,11 @@ hubbub_error handle_in_column_group(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- if (process_characters_expect_whitespace(treebuilder,
- token, true)) {
- err = HUBBUB_REPROCESS;
- }
+ err = process_characters_expect_whitespace(treebuilder,
+ token, true);
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -49,9 +47,10 @@ hubbub_error handle_in_column_group(hubbub_treebuilder *treebuilder,
if (type == HTML) {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else if (type == COL) {
- insert_element(treebuilder, &token->data.tag, false);
+ err = insert_element(treebuilder, &token->data.tag,
+ false);
/** \todo ack sc flag */
} else {
@@ -81,14 +80,14 @@ hubbub_error handle_in_column_group(hubbub_treebuilder *treebuilder,
}
if (handled || err == HUBBUB_REPROCESS) {
+ hubbub_error e;
hubbub_ns ns;
element_type otype;
void *node;
/* Pop the current node (which will be a colgroup) */
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
diff --git a/src/treebuilder/in_foreign_content.c b/src/treebuilder/in_foreign_content.c
index 1626e5b..a78e59f 100644
--- a/src/treebuilder/in_foreign_content.c
+++ b/src/treebuilder/in_foreign_content.c
@@ -325,9 +325,11 @@ static bool element_in_scope_in_non_html_ns(hubbub_treebuilder *treebuilder)
/**
* Process a token as if in the secondary insertion mode.
*/
-static void process_as_in_secondary(hubbub_treebuilder *treebuilder,
+static hubbub_error process_as_in_secondary(hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+ hubbub_error err;
+
/* Because we don't support calling insertion modes directly,
* instead we set the current mode to the secondary mode,
* call the token handler, and then reset the mode afterward
@@ -335,7 +337,11 @@ static void process_as_in_secondary(hubbub_treebuilder *treebuilder,
treebuilder->context.mode = treebuilder->context.second_mode;
- hubbub_treebuilder_token_handler(token, treebuilder);
+ err = hubbub_treebuilder_token_handler(token, treebuilder);
+ if (err != HUBBUB_OK) {
+ treebuilder->context.mode = IN_FOREIGN_CONTENT;
+ return err;
+ }
if (treebuilder->context.mode == treebuilder->context.second_mode)
treebuilder->context.mode = IN_FOREIGN_CONTENT;
@@ -344,6 +350,8 @@ static void process_as_in_secondary(hubbub_treebuilder *treebuilder,
!element_in_scope_in_non_html_ns(treebuilder)) {
treebuilder->context.mode = treebuilder->context.second_mode;
}
+
+ return HUBBUB_OK;
}
/**
@@ -357,11 +365,13 @@ static void foreign_break_out(hubbub_treebuilder *treebuilder)
while (stack[treebuilder->context.current_node].ns !=
HUBBUB_NS_HTML) {
+ hubbub_error e;
hubbub_ns ns;
element_type type;
void *node;
- element_stack_pop(treebuilder, &ns, &type, &node);
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -385,10 +395,10 @@ hubbub_error handle_in_foreign_content(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- append_text(treebuilder, &token->data.character);
+ err = append_text(treebuilder, &token->data.character);
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -416,7 +426,7 @@ hubbub_error handle_in_foreign_content(hubbub_treebuilder *treebuilder,
(cur_node == FOREIGNOBJECT ||
cur_node == DESC ||
cur_node == TITLE))) {
- process_as_in_secondary(treebuilder, token);
+ err = process_as_in_secondary(treebuilder, token);
} else if (type == B || type == BIG || type == BLOCKQUOTE ||
type == BODY || type == BR || type == CENTER ||
type == CODE || type == DD || type == DIV ||
@@ -474,16 +484,16 @@ hubbub_error handle_in_foreign_content(hubbub_treebuilder *treebuilder,
tag.ns = cur_node_ns;
if (token->data.tag.self_closing) {
- insert_element(treebuilder, &tag, false);
+ err = insert_element(treebuilder, &tag, false);
/** \todo ack sc flag */
} else {
- insert_element(treebuilder, &tag, true);
+ err = insert_element(treebuilder, &tag, true);
}
}
}
break;
case HUBBUB_TOKEN_END_TAG:
- process_as_in_secondary(treebuilder, token);
+ err = process_as_in_secondary(treebuilder, token);
break;
case HUBBUB_TOKEN_EOF:
foreign_break_out(treebuilder);
diff --git a/src/treebuilder/in_frameset.c b/src/treebuilder/in_frameset.c
index 10d1a8f..928e4cc 100644
--- a/src/treebuilder/in_frameset.c
+++ b/src/treebuilder/in_frameset.c
@@ -28,13 +28,16 @@ hubbub_error handle_in_frameset(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- if (process_characters_expect_whitespace(treebuilder,
- token, true)) {
- /** \todo parser error */
+ err = process_characters_expect_whitespace(treebuilder,
+ token, true);
+ if (err == HUBBUB_REPROCESS) {
+ /** \todo parse error */
+ /* Ignore the token */
+ err = HUBBUB_OK;
}
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -47,11 +50,13 @@ hubbub_error handle_in_frameset(hubbub_treebuilder *treebuilder,
&token->data.tag.name);
if (type == HTML) {
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else if (type == FRAMESET) {
- insert_element(treebuilder, &token->data.tag, true);
+ err = insert_element(treebuilder, &token->data.tag,
+ true);
} else if (type == FRAME) {
- insert_element(treebuilder, &token->data.tag, false);
+ err = insert_element(treebuilder, &token->data.tag,
+ false);
/** \todo ack sc flag */
} else if (type == NOFRAMES) {
err = handle_in_head(treebuilder, token);
@@ -66,6 +71,7 @@ hubbub_error handle_in_frameset(hubbub_treebuilder *treebuilder,
&token->data.tag.name);
if (type == FRAMESET) {
+ hubbub_error e;
hubbub_ns ns;
void *node;
@@ -75,10 +81,8 @@ hubbub_error handle_in_frameset(hubbub_treebuilder *treebuilder,
break;
}
- if (!element_stack_pop(treebuilder, &ns, &type,
- &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
diff --git a/src/treebuilder/in_head.c b/src/treebuilder/in_head.c
index 32d2ce0..8eb95d1 100644
--- a/src/treebuilder/in_head.c
+++ b/src/treebuilder/in_head.c
@@ -23,7 +23,7 @@
/**
* Process a meta tag as if "in head".
*
- * \param treebuilder The treebuilder instance
+ * \param treebuilder The treebuilder instance
* \param token The token to process
*/
static hubbub_error process_meta_in_head(hubbub_treebuilder *treebuilder,
@@ -33,13 +33,16 @@ static hubbub_error process_meta_in_head(hubbub_treebuilder *treebuilder,
uint16_t charset_enc = 0;
uint16_t content_type_enc = 0;
size_t i;
+ hubbub_error err = HUBBUB_OK;
- insert_element(treebuilder, &token->data.tag, false);
+ err = insert_element(treebuilder, &token->data.tag, false);
+ if (err != HUBBUB_OK)
+ return err;
/** \todo ack sc flag */
if (treebuilder->tree_handler->encoding_change == NULL)
- return HUBBUB_OK;
+ return err;
/* Grab UTF-16 MIBenums */
if (utf16 == 0) {
@@ -89,14 +92,11 @@ static hubbub_error process_meta_in_head(hubbub_treebuilder *treebuilder,
name = parserutils_charset_mibenum_to_name(charset_enc);
- /* 1 indicates the encoding should actually change */
- if (treebuilder->tree_handler->encoding_change(
- treebuilder->tree_handler->ctx, name) == 1) {
- return HUBBUB_ENCODINGCHANGE;
- }
+ err = treebuilder->tree_handler->encoding_change(
+ treebuilder->tree_handler->ctx, name);
}
- return HUBBUB_OK;
+ return err;
}
/**
@@ -118,7 +118,7 @@ hubbub_error handle_in_head(hubbub_treebuilder *treebuilder,
token, true);
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -132,30 +132,35 @@ hubbub_error handle_in_head(hubbub_treebuilder *treebuilder,
if (type == HTML) {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else if (type == BASE || type == COMMAND || type == LINK) {
- insert_element(treebuilder, &token->data.tag, false);
+ err = insert_element(treebuilder, &token->data.tag,
+ false);
/** \todo ack sc flag */
} else if (type == META) {
err = process_meta_in_head(treebuilder, token);
} else if (type == TITLE) {
- parse_generic_rcdata(treebuilder, token, true);
+ err = parse_generic_rcdata(treebuilder, token, true);
} else if (type == NOFRAMES || type == STYLE) {
- parse_generic_rcdata(treebuilder, token, false);
+ err = parse_generic_rcdata(treebuilder, token, false);
} else if (type == NOSCRIPT) {
if (treebuilder->context.enable_scripting) {
- parse_generic_rcdata(treebuilder, token, false);
+ err = parse_generic_rcdata(treebuilder, token,
+ false);
} else {
- insert_element(treebuilder, &token->data.tag,
- true);
+ err = insert_element(treebuilder,
+ &token->data.tag, true);
+ if (err != HUBBUB_OK)
+ return err;
+
treebuilder->context.mode = IN_HEAD_NOSCRIPT;
}
} else if (type == SCRIPT) {
/** \todo need to ensure that the client callback
* sets the parser-inserted/already-executed script
* flags. */
- parse_generic_rcdata(treebuilder, token, false);
+ err = parse_generic_rcdata(treebuilder, token, false);
} else if (type == HEAD) {
/** \todo parse error */
} else {
@@ -181,13 +186,13 @@ hubbub_error handle_in_head(hubbub_treebuilder *treebuilder,
}
if (handled || err == HUBBUB_REPROCESS) {
+ hubbub_error e;
hubbub_ns ns;
element_type otype;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
diff --git a/src/treebuilder/in_head_noscript.c b/src/treebuilder/in_head_noscript.c
index 6d30765..cf5061c 100644
--- a/src/treebuilder/in_head_noscript.c
+++ b/src/treebuilder/in_head_noscript.c
@@ -45,7 +45,7 @@ hubbub_error handle_in_head_noscript(hubbub_treebuilder *treebuilder,
if (type == HTML) {
/* Process as "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else if (type == NOSCRIPT) {
handled = true;
} else if (type == LINK || type == META || type == NOFRAMES ||
@@ -82,13 +82,13 @@ hubbub_error handle_in_head_noscript(hubbub_treebuilder *treebuilder,
}
if (handled || err == HUBBUB_REPROCESS) {
+ hubbub_error e;
hubbub_ns ns;
element_type otype;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
diff --git a/src/treebuilder/in_row.c b/src/treebuilder/in_row.c
index 79d6f6c..0c23bab 100644
--- a/src/treebuilder/in_row.c
+++ b/src/treebuilder/in_row.c
@@ -24,13 +24,13 @@ static void table_clear_stack(hubbub_treebuilder *treebuilder)
element_type cur_node = current_node(treebuilder);
while (cur_node != TR && cur_node != HTML) {
+ hubbub_error e;
hubbub_ns ns;
element_type type;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &type, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -51,6 +51,7 @@ static void table_clear_stack(hubbub_treebuilder *treebuilder)
*/
static hubbub_error act_as_if_end_tag_tr(hubbub_treebuilder *treebuilder)
{
+ hubbub_error e;
hubbub_ns ns;
element_type otype;
void *node;
@@ -58,9 +59,9 @@ static hubbub_error act_as_if_end_tag_tr(hubbub_treebuilder *treebuilder)
/** \todo fragment case */
table_clear_stack(treebuilder);
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx,
node);
@@ -92,7 +93,11 @@ hubbub_error handle_in_row(hubbub_treebuilder *treebuilder,
if (type == TH || type == TD) {
table_clear_stack(treebuilder);
- insert_element(treebuilder, &token->data.tag, true);
+ err = insert_element(treebuilder, &token->data.tag,
+ true);
+ if (err != HUBBUB_OK)
+ return err;
+
treebuilder->context.mode = IN_CELL;
/* ref node for formatting list */
@@ -101,11 +106,30 @@ hubbub_error handle_in_row(hubbub_treebuilder *treebuilder,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
- formatting_list_append(treebuilder,
+ err = formatting_list_append(treebuilder,
token->data.tag.ns, type,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
treebuilder->context.current_node);
+ if (err != HUBBUB_OK) {
+ hubbub_error e;
+ hubbub_ns ns;
+ element_type type;
+ void *node;
+
+ /* Revert changes */
+
+ e = remove_node_from_dom(treebuilder,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+ assert(e == HUBBUB_OK);
+
+ e = element_stack_pop(treebuilder, &ns, &type,
+ &node);
+ assert(e == HUBBUB_OK);
+
+ return err;
+ }
} else if (type == CAPTION || type == COL ||
type == COLGROUP || type == TBODY ||
type == TFOOT || type == THEAD || type == TR) {
@@ -121,7 +145,10 @@ hubbub_error handle_in_row(hubbub_treebuilder *treebuilder,
&token->data.tag.name);
if (type == TR) {
- (void)act_as_if_end_tag_tr(treebuilder);
+ /* We're done with this token, but act_as_if_end_tag_tr
+ * will return HUBBUB_REPROCESS. Therefore, ignore the
+ * return value. */
+ (void) act_as_if_end_tag_tr(treebuilder);
} else if (type == TABLE) {
err = act_as_if_end_tag_tr(treebuilder);
} else if (type == BODY || type == CAPTION || type == COL ||
diff --git a/src/treebuilder/in_select.c b/src/treebuilder/in_select.c
index 06fe287..cfddf4a 100644
--- a/src/treebuilder/in_select.c
+++ b/src/treebuilder/in_select.c
@@ -32,10 +32,10 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- append_text(treebuilder, &token->data.character);
+ err = append_text(treebuilder, &token->data.character);
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -49,26 +49,27 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder,
if (type == HTML) {
/* Process as if "in body" */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
} else if (type == OPTION) {
if (current_node(treebuilder) == OPTION) {
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ hubbub_error e;
+ e = element_stack_pop(treebuilder, &ns, &otype,
+ &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
node);
}
- insert_element(treebuilder, &token->data.tag, true);
+ err = insert_element(treebuilder, &token->data.tag,
+ true);
} else if (type == OPTGROUP) {
if (current_node(treebuilder) == OPTION) {
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ hubbub_error e;
+ e = element_stack_pop(treebuilder, &ns, &otype,
+ &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -76,31 +77,36 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder,
}
if (current_node(treebuilder) == OPTGROUP) {
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ hubbub_error e;
+ e = element_stack_pop(treebuilder, &ns, &otype,
+ &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
node);
}
- insert_element(treebuilder, &token->data.tag, true);
+ err = insert_element(treebuilder, &token->data.tag,
+ true);
} else if (type == SELECT || type == INPUT ||
type == TEXTAREA) {
if (element_in_scope(treebuilder, SELECT, true)) {
- element_stack_pop_until(treebuilder, SELECT);
+ hubbub_error e;
+ e = element_stack_pop_until(treebuilder,
+ SELECT);
+ assert(e == HUBBUB_OK);
reset_insertion_mode(treebuilder);
} else {
/* fragment case */
/** \todo parse error */
}
- if (type != SELECT) err = HUBBUB_REPROCESS;
+ if (type != SELECT)
+ err = HUBBUB_REPROCESS;
} else if (type == SCRIPT) {
- handle_in_head(treebuilder, token);
+ err = handle_in_head(treebuilder, token);
} else {
/** \todo parse error */
}
@@ -114,10 +120,10 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder,
if (type == OPTGROUP) {
if (current_node(treebuilder) == OPTION &&
prev_node(treebuilder) == OPTGROUP) {
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ hubbub_error e;
+ e = element_stack_pop(treebuilder, &ns, &otype,
+ &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -125,10 +131,10 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder,
}
if (current_node(treebuilder) == OPTGROUP) {
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ hubbub_error e;
+ e = element_stack_pop(treebuilder, &ns, &otype,
+ &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -138,10 +144,10 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder,
}
} else if (type == OPTION) {
if (current_node(treebuilder) == OPTION) {
- if (!element_stack_pop(treebuilder, &ns, &otype,
- &node)) {
- /** \todo errors */
- }
+ hubbub_error e;
+ e = element_stack_pop(treebuilder, &ns, &otype,
+ &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -151,7 +157,10 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder,
}
} else if (type == SELECT) {
if (element_in_scope(treebuilder, SELECT, true)) {
- element_stack_pop_until(treebuilder, SELECT);
+ hubbub_error e;
+ e = element_stack_pop_until(treebuilder,
+ SELECT);
+ assert(e == HUBBUB_OK);
reset_insertion_mode(treebuilder);
} else {
/* fragment case */
diff --git a/src/treebuilder/in_select_in_table.c b/src/treebuilder/in_select_in_table.c
index 5ddce11..b22fbc1 100644
--- a/src/treebuilder/in_select_in_table.c
+++ b/src/treebuilder/in_select_in_table.c
@@ -43,9 +43,13 @@ hubbub_error handle_in_select_in_table(hubbub_treebuilder *treebuilder,
element_in_scope(treebuilder, type,
true)) ||
token->type == HUBBUB_TOKEN_START_TAG) {
+ hubbub_error e;
+
/** \todo fragment case */
- element_stack_pop_until(treebuilder, SELECT);
+ e = element_stack_pop_until(treebuilder,
+ SELECT);
+ assert(e == HUBBUB_OK);
reset_insertion_mode(treebuilder);
err = HUBBUB_REPROCESS;
}
diff --git a/src/treebuilder/in_table.c b/src/treebuilder/in_table.c
index ac5e6c5..f5ffdb2 100644
--- a/src/treebuilder/in_table.c
+++ b/src/treebuilder/in_table.c
@@ -27,7 +27,10 @@ static inline void clear_stack_table_context(hubbub_treebuilder *treebuilder)
void *node;
while (type != TABLE && type != HTML) {
- element_stack_pop(treebuilder, &ns, &type, &node);
+ hubbub_error e;
+
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -35,18 +38,19 @@ static inline void clear_stack_table_context(hubbub_treebuilder *treebuilder)
type = current_node(treebuilder);
}
-
- return;
}
/**
* Process an input start tag in the "in table" insertion mode.
*/
-static inline bool process_input_in_table(hubbub_treebuilder *treebuilder,
+static inline hubbub_error process_input_in_table(
+ hubbub_treebuilder *treebuilder,
const hubbub_token *token)
{
+ hubbub_error err = HUBBUB_REPROCESS;
size_t i;
+
for (i = 0; i < token->data.tag.n_attributes; i++) {
hubbub_attribute *attr = &token->data.tag.attributes[i];
@@ -56,12 +60,10 @@ static inline bool process_input_in_table(hubbub_treebuilder *treebuilder,
}
/** \todo parse error */
- insert_element(treebuilder, &token->data.tag, true);
-
- return true;
+ err = insert_element(treebuilder, &token->data.tag, true);
}
- return false;
+ return err;
}
@@ -85,12 +87,13 @@ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder,
].tainted) {
handled = false;
} else {
- handled = !process_characters_expect_whitespace(
+ err = process_characters_expect_whitespace(
treebuilder, token, true);
+ handled = (err == HUBBUB_OK);
}
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
break;
@@ -107,19 +110,50 @@ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder,
if (type == CAPTION) {
clear_stack_table_context(treebuilder);
+
treebuilder->tree_handler->ref_node(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[
treebuilder->context.current_node].node);
- formatting_list_append(treebuilder,
+
+ err = formatting_list_append(treebuilder,
token->data.tag.ns, type,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
treebuilder->context.current_node);
+ if (err != HUBBUB_OK) {
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ treebuilder->context.element_stack[
+ treebuilder->context.current_node].node);
+
+ return err;
+ }
+
+ err = insert_element(treebuilder, &token->data.tag,
+ true);
+ if (err != HUBBUB_OK) {
+ hubbub_error e;
+ hubbub_ns ns;
+ element_type type;
+ void *node;
+ uint32_t index;
+
+ e = formatting_list_remove(treebuilder,
+ treebuilder->context.formatting_list_end,
+ &ns, &type, &node, &index);
+ assert(e == HUBBUB_OK);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ node);
+
+ return err;
+ }
- insert_element(treebuilder, &token->data.tag, true);
treebuilder->context.mode = IN_CAPTION;
} else if (type == COLGROUP || type == COL) {
+ hubbub_error e;
hubbub_tag tag = token->data.tag;
if (type == COL) {
@@ -133,10 +167,15 @@ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder,
}
clear_stack_table_context(treebuilder);
- insert_element(treebuilder, &tag, true);
+
+ e = insert_element(treebuilder, &tag, true);
+ if (e != HUBBUB_OK)
+ return e;
+
treebuilder->context.mode = IN_COLUMN_GROUP;
} else if (type == TBODY || type == TFOOT || type == THEAD ||
type == TD || type == TH || type == TR) {
+ hubbub_error e;
hubbub_tag tag = token->data.tag;
if (type == TD || type == TH || type == TR) {
@@ -150,20 +189,28 @@ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder,
}
clear_stack_table_context(treebuilder);
- insert_element(treebuilder, &tag, true);
+
+ e = insert_element(treebuilder, &tag, true);
+ if (e != HUBBUB_OK)
+ return e;
+
treebuilder->context.mode = IN_TABLE_BODY;
} else if (type == TABLE) {
+ hubbub_error e;
/** \todo parse error */
/* This should match "</table>" handling */
- element_stack_pop_until(treebuilder, TABLE);
+ e = element_stack_pop_until(treebuilder, TABLE);
+ assert(e == HUBBUB_OK);
+
reset_insertion_mode(treebuilder);
err = HUBBUB_REPROCESS;
} else if (!tainted && (type == STYLE || type == SCRIPT)) {
err = handle_in_head(treebuilder, token);
} else if (!tainted && type == INPUT) {
- handled = process_input_in_table(treebuilder, token);
+ err = process_input_in_table(treebuilder, token);
+ handled = (err == HUBBUB_OK);
} else {
handled = false;
}
@@ -175,9 +222,12 @@ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder,
&token->data.tag.name);
if (type == TABLE) {
+ hubbub_error e;
/** \todo fragment case */
- element_stack_pop_until(treebuilder, TABLE);
+ e = element_stack_pop_until(treebuilder, TABLE);
+ assert(e == HUBBUB_OK);
+
reset_insertion_mode(treebuilder);
} else if (type == BODY || type == CAPTION || type == COL ||
type == COLGROUP || type == HTML ||
@@ -197,7 +247,7 @@ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder,
treebuilder->context.in_table_foster = true;
/** \todo parse error */
- handle_in_body(treebuilder, token);
+ err = handle_in_body(treebuilder, token);
treebuilder->context.in_table_foster = false;
}
diff --git a/src/treebuilder/in_table_body.c b/src/treebuilder/in_table_body.c
index 985a893..b99dd08 100644
--- a/src/treebuilder/in_table_body.c
+++ b/src/treebuilder/in_table_body.c
@@ -25,13 +25,13 @@ static void table_clear_stack(hubbub_treebuilder *treebuilder)
while (cur_node != TBODY && cur_node != TFOOT &&
cur_node != THEAD && cur_node != HTML) {
+ hubbub_error e;
hubbub_ns ns;
element_type type;
void *node;
- if (!element_stack_pop(treebuilder, &ns, &type, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -55,6 +55,7 @@ static hubbub_error table_sub_start_or_table_end(hubbub_treebuilder *treebuilder
if (element_in_scope(treebuilder, TBODY, true) ||
element_in_scope(treebuilder, THEAD, true) ||
element_in_scope(treebuilder, TFOOT, true)) {
+ hubbub_error e;
hubbub_ns ns;
element_type otype;
void *node;
@@ -64,9 +65,8 @@ static hubbub_error table_sub_start_or_table_end(hubbub_treebuilder *treebuilder
/* "Act as if an end tag with the same name as the current
* node had been seen" -- this behaviour should be identical
* to handling for (tbody/tfoot/thead) end tags in this mode */
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+ e = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -103,8 +103,11 @@ hubbub_error handle_in_table_body(hubbub_treebuilder *treebuilder,
if (type == TR) {
table_clear_stack(treebuilder);
- insert_element(treebuilder, &token->data.tag, true);
- treebuilder->context.mode = IN_ROW;
+
+ err = insert_element(treebuilder, &token->data.tag,
+ true);
+ if (err == HUBBUB_OK)
+ treebuilder->context.mode = IN_ROW;
} else if (type == TH || type == TD) {
hubbub_tag tag;
@@ -119,10 +122,13 @@ hubbub_error handle_in_table_body(hubbub_treebuilder *treebuilder,
tag.attributes = NULL;
table_clear_stack(treebuilder);
- insert_element(treebuilder, &tag, true);
- treebuilder->context.mode = IN_ROW;
- err = HUBBUB_REPROCESS;
+ err = insert_element(treebuilder, &tag, true);
+ if (err == HUBBUB_OK) {
+ treebuilder->context.mode = IN_ROW;
+
+ err = HUBBUB_REPROCESS;
+ }
} else if (type == CAPTION || type == COL ||
type == COLGROUP || type == TBODY ||
type == TFOOT || type == THEAD) {
@@ -142,15 +148,16 @@ hubbub_error handle_in_table_body(hubbub_treebuilder *treebuilder,
/** \todo parse error */
/* Ignore the token */
} else {
+ hubbub_error e;
hubbub_ns ns;
element_type otype;
void *node;
table_clear_stack(treebuilder);
- if (!element_stack_pop(treebuilder, &ns,
- &otype, &node)) {
- /** \todo errors */
- }
+
+ e = element_stack_pop(treebuilder, &ns,
+ &otype, &node);
+ assert(e == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
diff --git a/src/treebuilder/initial.c b/src/treebuilder/initial.c
index 6ead570..5f0796c 100644
--- a/src/treebuilder/initial.c
+++ b/src/treebuilder/initial.c
@@ -228,53 +228,50 @@ hubbub_error handle_initial(hubbub_treebuilder *treebuilder,
switch (token->type) {
case HUBBUB_TOKEN_CHARACTER:
- if (process_characters_expect_whitespace(treebuilder, token,
- false)) {
+ err = process_characters_expect_whitespace(treebuilder, token,
+ false);
+ if (err == HUBBUB_REPROCESS) {
/** \todo parse error */
treebuilder->tree_handler->set_quirks_mode(
treebuilder->tree_handler->ctx,
HUBBUB_QUIRKS_MODE_FULL);
treebuilder->context.mode = BEFORE_HTML;
- err = HUBBUB_REPROCESS;
}
break;
case HUBBUB_TOKEN_COMMENT:
- process_comment_append(treebuilder, token,
+ err = process_comment_append(treebuilder, token,
treebuilder->context.document);
break;
case HUBBUB_TOKEN_DOCTYPE:
{
- int success;
void *doctype, *appended;
const hubbub_doctype *cdoc;
/** \todo parse error */
- success = treebuilder->tree_handler->create_doctype(
+ err = treebuilder->tree_handler->create_doctype(
treebuilder->tree_handler->ctx,
&token->data.doctype,
&doctype);
- if (success != 0) {
- /** \todo errors */
- }
+ if (err != HUBBUB_OK)
+ return err;
/* Append to Document node */
- success = treebuilder->tree_handler->append_child(
+ err = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
treebuilder->context.document,
doctype, &appended);
- if (success != 0) {
- /** \todo errors */
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- doctype);
- }
treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, appended);
+ treebuilder->tree_handler->ctx,
+ doctype);
+
+ if (err != HUBBUB_OK)
+ return err;
+
treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, doctype);
+ treebuilder->tree_handler->ctx, appended);
cdoc = &token->data.doctype;
diff --git a/src/treebuilder/internal.h b/src/treebuilder/internal.h
index 2b20fbf..311996c 100644
--- a/src/treebuilder/internal.h
+++ b/src/treebuilder/internal.h
@@ -73,6 +73,8 @@ typedef struct formatting_list_entry
typedef struct hubbub_treebuilder_context
{
insertion_mode mode; /**< The current insertion mode */
+ uint32_t mode_state; /**< Insertion mode specific state */
+
insertion_mode second_mode; /**< The secondary insertion mode */
#define ELEMENT_STACK_CHUNK 128
@@ -134,22 +136,25 @@ hubbub_error hubbub_treebuilder_token_handler(
hubbub_error process_characters_expect_whitespace(
hubbub_treebuilder *treebuilder, const hubbub_token *token,
bool insert_into_current_node);
-void process_comment_append(hubbub_treebuilder *treebuilder,
+hubbub_error process_comment_append(hubbub_treebuilder *treebuilder,
const hubbub_token *token, void *parent);
-void parse_generic_rcdata(hubbub_treebuilder *treebuilder,
+hubbub_error parse_generic_rcdata(hubbub_treebuilder *treebuilder,
const hubbub_token *token, bool rcdata);
uint32_t element_in_scope(hubbub_treebuilder *treebuilder,
element_type type, bool in_table);
-void reconstruct_active_formatting_list(hubbub_treebuilder *treebuilder);
+hubbub_error reconstruct_active_formatting_list(
+ hubbub_treebuilder *treebuilder);
void clear_active_formatting_list_to_marker(
hubbub_treebuilder *treebuilder);
-void insert_element(hubbub_treebuilder *treebuilder,
+hubbub_error remove_node_from_dom(hubbub_treebuilder *treebuilder,
+ void *node);
+hubbub_error insert_element(hubbub_treebuilder *treebuilder,
const hubbub_tag *tag_name, bool push);
void close_implied_end_tags(hubbub_treebuilder *treebuilder,
element_type except);
void reset_insertion_mode(hubbub_treebuilder *treebuilder);
-void append_text(hubbub_treebuilder *treebuilder,
+hubbub_error append_text(hubbub_treebuilder *treebuilder,
const hubbub_string *string);
element_type element_type_from_name(hubbub_treebuilder *treebuilder,
@@ -160,30 +165,31 @@ bool is_scoping_element(element_type type);
bool is_formatting_element(element_type type);
bool is_phrasing_element(element_type type);
-bool element_stack_push(hubbub_treebuilder *treebuilder,
+hubbub_error element_stack_push(hubbub_treebuilder *treebuilder,
hubbub_ns ns, element_type type, void *node);
-bool element_stack_pop(hubbub_treebuilder *treebuilder,
+hubbub_error element_stack_pop(hubbub_treebuilder *treebuilder,
hubbub_ns *ns, element_type *type, void **node);
-bool element_stack_pop_until(hubbub_treebuilder *treebuilder,
+hubbub_error element_stack_pop_until(hubbub_treebuilder *treebuilder,
element_type type);
-bool element_stack_remove(hubbub_treebuilder *treebuilder, uint32_t index,
- hubbub_ns *ns, element_type *type, void **removed);
+hubbub_error element_stack_remove(hubbub_treebuilder *treebuilder,
+ uint32_t index, hubbub_ns *ns, element_type *type,
+ void **removed);
uint32_t current_table(hubbub_treebuilder *treebuilder);
element_type current_node(hubbub_treebuilder *treebuilder);
element_type prev_node(hubbub_treebuilder *treebuilder);
-bool formatting_list_append(hubbub_treebuilder *treebuilder,
+hubbub_error formatting_list_append(hubbub_treebuilder *treebuilder,
hubbub_ns ns, element_type type, void *node,
uint32_t stack_index);
-bool formatting_list_insert(hubbub_treebuilder *treebuilder,
+hubbub_error formatting_list_insert(hubbub_treebuilder *treebuilder,
formatting_list_entry *prev, formatting_list_entry *next,
hubbub_ns ns, element_type type, void *node,
uint32_t stack_index);
-bool formatting_list_remove(hubbub_treebuilder *treebuilder,
+hubbub_error formatting_list_remove(hubbub_treebuilder *treebuilder,
formatting_list_entry *entry,
hubbub_ns *ns, element_type *type, void **node,
uint32_t *stack_index);
-bool formatting_list_replace(hubbub_treebuilder *treebuilder,
+hubbub_error formatting_list_replace(hubbub_treebuilder *treebuilder,
formatting_list_entry *entry,
hubbub_ns ns, element_type type, void *node,
uint32_t stack_index,
@@ -200,7 +206,8 @@ void adjust_foreign_attributes(hubbub_treebuilder *treebuilder,
hubbub_tag *tag);
/* in_body.c */
-void *aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder, void *node);
+hubbub_error aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder,
+ void *node, void **inserted);
#ifndef NDEBUG
#include <stdio.h>
diff --git a/src/treebuilder/treebuilder.c b/src/treebuilder/treebuilder.c
index ec5f825..33f8eef 100644
--- a/src/treebuilder/treebuilder.c
+++ b/src/treebuilder/treebuilder.c
@@ -374,9 +374,10 @@ hubbub_error hubbub_treebuilder_token_handler(const hubbub_token *token,
* \param token The character token
* \param insert_into_current_node Whether to insert whitespace into
* current node
- * \return True if the token needs reprocessing
- * (token data updated to skip any leading whitespace),
- * false if it contained only whitespace
+ * \return HUBBUB_REPROCESS if the token needs reprocessing
+ * (token data updated to skip any leading whitespace),
+ * HUBBUB_OK if it contained only whitespace,
+ * appropriate error otherwise
*/
hubbub_error process_characters_expect_whitespace(
hubbub_treebuilder *treebuilder,
@@ -393,12 +394,15 @@ hubbub_error process_characters_expect_whitespace(
}
if (c > 0 && insert_into_current_node) {
+ hubbub_error error;
hubbub_string temp;
temp.ptr = data;
temp.len = c;
- append_text(treebuilder, &temp);
+ error = append_text(treebuilder, &temp);
+ if (error != HUBBUB_OK)
+ return error;
}
/* Non-whitespace characters in token, so reprocess */
@@ -419,39 +423,41 @@ hubbub_error process_characters_expect_whitespace(
* \param treebuilder The treebuilder instance
* \param token The comment token
* \param parent The node to append to
+ * \return HUBBUB_OK on success, appropriate error otherwise
*/
-void process_comment_append(hubbub_treebuilder *treebuilder,
+hubbub_error process_comment_append(hubbub_treebuilder *treebuilder,
const hubbub_token *token, void *parent)
{
+ hubbub_error error = HUBBUB_OK;
element_type type = current_node(treebuilder);
- int success;
void *comment, *appended;
- success = treebuilder->tree_handler->create_comment(
+ error = treebuilder->tree_handler->create_comment(
treebuilder->tree_handler->ctx,
&token->data.comment, &comment);
- if (success != 0) {
- /** \todo errors */
- }
+ if (error != HUBBUB_OK)
+ return error;
if (treebuilder->context.in_table_foster &&
(type == TABLE || type == TBODY || type == TFOOT ||
type == THEAD || type == TR)) {
- appended = aa_insert_into_foster_parent(treebuilder, comment);
+ error = aa_insert_into_foster_parent(treebuilder, comment,
+ &appended);
} else {
- success = treebuilder->tree_handler->append_child(
+ error = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
parent, comment, &appended);
- if (success != 0) {
- /** \todo errors */
- }
+ }
+ if (error == HUBBUB_OK) {
treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, comment);
+ treebuilder->tree_handler->ctx, appended);
}
treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, appended);
+ treebuilder->tree_handler->ctx, comment);
+
+ return error;
}
/**
@@ -460,26 +466,34 @@ void process_comment_append(hubbub_treebuilder *treebuilder,
* \param treebuilder The treebuilder instance
* \param token The current token
* \param rcdata True for RCDATA, false for CDATA
+ * \return HUBBUB_OK on success, appropriate error otherwise
*/
-void parse_generic_rcdata(hubbub_treebuilder *treebuilder,
+hubbub_error parse_generic_rcdata(hubbub_treebuilder *treebuilder,
const hubbub_token *token, bool rcdata)
{
+ hubbub_error error;
element_type type;
hubbub_tokeniser_optparams params;
type = element_type_from_name(treebuilder, &token->data.tag.name);
- insert_element(treebuilder, &token->data.tag, true);
+ error = insert_element(treebuilder, &token->data.tag, true);
+ if (error != HUBBUB_OK)
+ return error;
params.content_model.model = rcdata ? HUBBUB_CONTENT_MODEL_RCDATA
: HUBBUB_CONTENT_MODEL_CDATA;
- hubbub_tokeniser_setopt(treebuilder->tokeniser,
+ error = hubbub_tokeniser_setopt(treebuilder->tokeniser,
HUBBUB_TOKENISER_CONTENT_MODEL, &params);
+ /* There is no way that setopt can fail. Ensure this. */
+ assert(error == HUBBUB_OK);
treebuilder->context.collect.mode = treebuilder->context.mode;
treebuilder->context.collect.type = type;
treebuilder->context.mode = GENERIC_RCDATA;
+
+ return HUBBUB_OK;
}
/**
@@ -496,7 +510,7 @@ uint32_t element_in_scope(hubbub_treebuilder *treebuilder,
uint32_t node;
if (treebuilder->context.element_stack == NULL)
- return false;
+ return 0;
assert((signed) treebuilder->context.current_node >= 0);
@@ -531,19 +545,22 @@ uint32_t element_in_scope(hubbub_treebuilder *treebuilder,
* Reconstruct the list of active formatting elements
*
* \param treebuilder Treebuilder instance containing list
+ * \return HUBBUB_OK on success, appropriate error otherwise.
*/
-void reconstruct_active_formatting_list(hubbub_treebuilder *treebuilder)
+hubbub_error reconstruct_active_formatting_list(hubbub_treebuilder *treebuilder)
{
- formatting_list_entry *entry;
+ hubbub_error error = HUBBUB_OK;
+ formatting_list_entry *entry, *initial_entry;
+ uint32_t sp = treebuilder->context.current_node;
if (treebuilder->context.formatting_list == NULL)
- return;
+ return HUBBUB_OK;
entry = treebuilder->context.formatting_list_end;
/* Assumption: HTML and TABLE elements are not inserted into the list */
if (is_scoping_element(entry->details.type) || entry->stack_index != 0)
- return;
+ return HUBBUB_OK;
while (entry->prev != NULL) {
entry = entry->prev;
@@ -555,26 +572,23 @@ void reconstruct_active_formatting_list(hubbub_treebuilder *treebuilder)
}
}
+ /* Save initial entry for later */
+ initial_entry = entry;
+
+ /* Process formatting list entries, cloning nodes and
+ * inserting them into the DOM and element stack */
while (entry != NULL) {
- int success;
void *clone, *appended;
- hubbub_ns prev_ns;
- element_type prev_type;
- void *prev_node;
- uint32_t prev_stack_index;
bool foster;
-
element_type type = current_node(treebuilder);
- success = treebuilder->tree_handler->clone_node(
+ error = treebuilder->tree_handler->clone_node(
treebuilder->tree_handler->ctx,
entry->details.node,
false,
&clone);
- if (success != 0) {
- /** \todo handle errors */
- return;
- }
+ if (error != HUBBUB_OK)
+ goto cleanup;
foster = treebuilder->context.in_table_foster &&
(type == TABLE || type == TBODY ||
@@ -582,68 +596,130 @@ void reconstruct_active_formatting_list(hubbub_treebuilder *treebuilder)
type == TR);
if (foster) {
- appended = aa_insert_into_foster_parent(treebuilder,
- clone);
- treebuilder->tree_handler->ref_node(
- treebuilder->tree_handler->ctx,
- appended);
+ error = aa_insert_into_foster_parent(treebuilder,
+ clone, &appended);
} else {
- success = treebuilder->tree_handler->append_child(
+ error = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
clone,
&appended);
+ }
- if (success != 0) {
- /** \todo handle errors */
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- clone);
- return;
- }
+ /* No longer interested in clone */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ clone);
- if (appended != clone) {
- /* Transfer the reference we hold on clone to
- * appended. We're no longer interested in
- * clone.*/
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- clone);
- treebuilder->tree_handler->ref_node(
- treebuilder->tree_handler->ctx,
- appended);
- }
- }
+ if (error != HUBBUB_OK)
+ goto cleanup;
+
+ error = element_stack_push(treebuilder, entry->details.ns,
+ entry->details.type, appended);
+ if (error != HUBBUB_OK) {
+ hubbub_error err;
- /* At this point, appended's reference count will be 2 */
+ err = remove_node_from_dom(treebuilder, appended);
+ assert(err == HUBBUB_OK);
- if (!element_stack_push(treebuilder,
- entry->details.ns, entry->details.type,
- appended)) {
- /** \todo handle memory exhaustion */
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
appended);
+
+ goto cleanup;
}
- if (!formatting_list_replace(treebuilder, entry,
+ entry = entry->next;
+ }
+
+ /* Now, replace the formatting list entries */
+ for (entry = initial_entry; entry != NULL; entry = entry->next) {
+ void *node;
+ hubbub_ns prev_ns;
+ element_type prev_type;
+ void *prev_node;
+ uint32_t prev_stack_index;
+
+ node = treebuilder->context.element_stack[++sp].node;
+
+ treebuilder->tree_handler->ref_node(
+ treebuilder->tree_handler->ctx, node);
+
+ error = formatting_list_replace(treebuilder, entry,
entry->details.ns, entry->details.type,
- appended, treebuilder->context.current_node,
+ node, sp,
&prev_ns, &prev_type, &prev_node,
- &prev_stack_index)) {
- /** \todo handle errors */
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx,
- appended);
- }
+ &prev_stack_index);
+ /* Cannot fail. Ensure this. */
+ assert(error == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
prev_node);
+ }
- entry = entry->next;
+ return HUBBUB_OK;
+
+cleanup:
+ /* An error occurred while cloning nodes and inserting them.
+ * We must restore the state on entry here. */
+ while (treebuilder->context.current_node > sp) {
+ hubbub_ns ns;
+ element_type type;
+ void *node;
+ hubbub_error err;
+
+ err = element_stack_pop(treebuilder, &ns, &type, &node);
+ assert(err == HUBBUB_OK);
+
+ err = remove_node_from_dom(treebuilder, node);
+ assert(err == HUBBUB_OK);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ node);
+ }
+
+ return error;
+}
+
+/**
+ * Remove a node from the DOM
+ *
+ * \param treebuilder Treebuilder instance
+ * \param node Node to remove
+ * \return HUBBUB_OK on success, appropriate error otherwise.
+ */
+hubbub_error remove_node_from_dom(hubbub_treebuilder *treebuilder, void *node)
+{
+ hubbub_error err;
+ void *parent = NULL;
+ void *removed;
+
+ err = treebuilder->tree_handler->get_parent(
+ treebuilder->tree_handler->ctx,
+ node, false, &parent);
+ if (err != HUBBUB_OK)
+ return err;
+
+ if (parent != NULL) {
+ err = treebuilder->tree_handler->remove_child(
+ treebuilder->tree_handler->ctx,
+ parent, node, &removed);
+ if (err != HUBBUB_OK)
+ return err;
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ parent);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ removed);
}
+
+ return HUBBUB_OK;
}
/**
@@ -661,14 +737,15 @@ void clear_active_formatting_list_to_marker(hubbub_treebuilder *treebuilder)
element_type type;
void *node;
uint32_t stack_index;
+ hubbub_error error;
if (is_scoping_element(entry->details.type))
done = true;
- if (!formatting_list_remove(treebuilder, entry,
- &ns, &type, &node, &stack_index)) {
- /** \todo handle errors */
- }
+ error = formatting_list_remove(treebuilder, entry,
+ &ns, &type, &node, &stack_index);
+ /* Can't fail. Ensure this. */
+ assert(error == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -686,56 +763,82 @@ void clear_active_formatting_list_to_marker(hubbub_treebuilder *treebuilder)
* \param treebuilder The treebuilder instance
* \param tag The element to insert
* \param push Whether to push the element onto the stack
+ * \return HUBBUB_OK on success, appropriate error otherwise.
*/
-void insert_element(hubbub_treebuilder *treebuilder, const hubbub_tag *tag,
- bool push)
+hubbub_error insert_element(hubbub_treebuilder *treebuilder,
+ const hubbub_tag *tag, bool push)
{
element_type type = current_node(treebuilder);
- int success;
+ hubbub_error error;
void *node, *appended;
- success = treebuilder->tree_handler->create_element(
+ error = treebuilder->tree_handler->create_element(
treebuilder->tree_handler->ctx, tag, &node);
- if (success != 0) {
- /** \todo errors */
- }
+ if (error != HUBBUB_OK)
+ return error;
if (treebuilder->context.in_table_foster &&
(type == TABLE || type == TBODY || type == TFOOT ||
type == THEAD || type == TR)) {
- appended = aa_insert_into_foster_parent(treebuilder, node);
+ error = aa_insert_into_foster_parent(treebuilder, node,
+ &appended);
} else {
- success = treebuilder->tree_handler->append_child(
+ error = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
node, &appended);
- if (success != 0) {
- /** \todo errors */
- }
-
- treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, node);
}
+ /* No longer interested in node */
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx, node);
+
+ if (error != HUBBUB_OK)
+ return error;
+
type = element_type_from_name(treebuilder, &tag->name);
if (treebuilder->context.form_element != NULL &&
is_form_associated(type)) {
/* Consideration of @form is left to the client */
- treebuilder->tree_handler->form_associate(
+ error = treebuilder->tree_handler->form_associate(
treebuilder->tree_handler->ctx,
treebuilder->context.form_element,
appended);
+ if (error != HUBBUB_OK) {
+ hubbub_error err;
+
+ err = remove_node_from_dom(treebuilder, appended);
+ assert(err == HUBBUB_OK);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ appended);
+
+ return error;
+ }
}
if (push) {
- if (!element_stack_push(treebuilder, tag->ns, type, appended)) {
- /** \todo errors */
+ error = element_stack_push(treebuilder,
+ tag->ns, type, appended);
+ if (error != HUBBUB_OK) {
+ hubbub_error err;
+
+ err = remove_node_from_dom(treebuilder, appended);
+ assert(err == HUBBUB_OK);
+
+ treebuilder->tree_handler->unref_node(
+ treebuilder->tree_handler->ctx,
+ appended);
+ return error;
}
} else {
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx, appended);
}
+
+ return HUBBUB_OK;
}
/**
@@ -756,6 +859,7 @@ void close_implied_end_tags(hubbub_treebuilder *treebuilder,
while (type == DD || type == DT || type == LI || type == OPTION ||
type == OPTGROUP || type == P || type == RP ||
type == RT) {
+ hubbub_error error;
hubbub_ns ns;
element_type otype;
void *node;
@@ -763,9 +867,8 @@ void close_implied_end_tags(hubbub_treebuilder *treebuilder,
if (except != UNKNOWN && type == except)
break;
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo errors */
- }
+ error = element_stack_pop(treebuilder, &ns, &otype, &node);
+ assert(error == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
@@ -844,40 +947,42 @@ void reset_insertion_mode(hubbub_treebuilder *treebuilder)
*
* \param treebuilder The treebuilder instance
* \param string The string to append
+ * \return HUBBUB_OK on success, appropriate error otherwise
*/
-void append_text(hubbub_treebuilder *treebuilder,
+hubbub_error append_text(hubbub_treebuilder *treebuilder,
const hubbub_string *string)
{
element_type type = current_node(treebuilder);
- int success;
+ hubbub_error error = HUBBUB_OK;
void *text, *appended;
- success = treebuilder->tree_handler->create_text(
+ error = treebuilder->tree_handler->create_text(
treebuilder->tree_handler->ctx, string, &text);
- if (success != 0) {
- /** \todo errors */
- }
+ if (error != HUBBUB_OK)
+ return error;
if (treebuilder->context.in_table_foster &&
(type == TABLE || type == TBODY || type == TFOOT ||
type == THEAD || type == TR)) {
- appended = aa_insert_into_foster_parent(treebuilder, text);
+ error = aa_insert_into_foster_parent(treebuilder, text,
+ &appended);
} else {
- success = treebuilder->tree_handler->append_child(
+ error = treebuilder->tree_handler->append_child(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[
treebuilder->context.current_node].node,
text, &appended);
- if (success != 0) {
- /** \todo errors */
- }
-
+ }
+
+ if (error == HUBBUB_OK) {
treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, text);
+ treebuilder->tree_handler->ctx, appended);
}
treebuilder->tree_handler->unref_node(
- treebuilder->tree_handler->ctx, appended);
+ treebuilder->tree_handler->ctx, text);
+
+ return error;
}
/**
@@ -974,9 +1079,9 @@ bool is_form_associated(element_type type)
* \param ns The namespace of element being pushed
* \param type The type of element being pushed
* \param node The node to push
- * \return True on success, false on memory exhaustion
+ * \return HUBBUB_OK on success, appropriate error otherwise.
*/
-bool element_stack_push(hubbub_treebuilder *treebuilder,
+hubbub_error element_stack_push(hubbub_treebuilder *treebuilder,
hubbub_ns ns, element_type type, void *node)
{
uint32_t slot = treebuilder->context.current_node + 1;
@@ -990,7 +1095,7 @@ bool element_stack_push(hubbub_treebuilder *treebuilder,
treebuilder->alloc_pw);
if (temp == NULL)
- return false;
+ return HUBBUB_NOMEM;
treebuilder->context.element_stack = temp;
treebuilder->context.stack_alloc += ELEMENT_STACK_CHUNK;
@@ -1002,7 +1107,7 @@ bool element_stack_push(hubbub_treebuilder *treebuilder,
treebuilder->context.current_node = slot;
- return true;
+ return HUBBUB_OK;
}
/**
@@ -1012,9 +1117,9 @@ bool element_stack_push(hubbub_treebuilder *treebuilder,
* \param ns Pointer to location to receive element namespace
* \param type Pointer to location to receive element type
* \param node Pointer to location to receive node
- * \return True on success, false on memory exhaustion.
+ * \return HUBBUB_OK on success, appropriate error otherwise.
*/
-bool element_stack_pop(hubbub_treebuilder *treebuilder,
+hubbub_error element_stack_pop(hubbub_treebuilder *treebuilder,
hubbub_ns *ns, element_type *type, void **node)
{
element_context *stack = treebuilder->context.element_stack;
@@ -1055,26 +1160,26 @@ bool element_stack_pop(hubbub_treebuilder *treebuilder,
treebuilder->context.current_node = slot - 1;
assert((signed) treebuilder->context.current_node >= 0);
- return true;
+ return HUBBUB_OK;
}
/**
* Pop elements until an element of type "element" has been popped.
*
- * \return True on success, false on memory exhaustion.
+ * \return HUBBUB_OK on success, appropriate error otherwise.
*/
-bool element_stack_pop_until(hubbub_treebuilder *treebuilder,
+hubbub_error element_stack_pop_until(hubbub_treebuilder *treebuilder,
element_type type)
{
element_type otype = UNKNOWN;
void *node;
hubbub_ns ns;
+ hubbub_error error;
while (otype != type) {
- if (!element_stack_pop(treebuilder, &ns, &otype, &node)) {
- /** \todo error -- never happens */
- return false;
- }
+ error = element_stack_pop(treebuilder, &ns, &otype, &node);
+ /* No error can occur here. Ensure this. */
+ assert(error == HUBBUB_OK);
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx, node);
@@ -1082,7 +1187,7 @@ bool element_stack_pop_until(hubbub_treebuilder *treebuilder,
assert((signed) treebuilder->context.current_node >= 0);
}
- return true;
+ return HUBBUB_OK;
}
/**
@@ -1093,10 +1198,11 @@ bool element_stack_pop_until(hubbub_treebuilder *treebuilder,
* \param ns Pointer to location to receive namespace
* \param type Pointer to location to receive type
* \param removed Pointer to location to receive removed node
- * \return true on success, false on memory exhaustion
+ * \return HUBBUB_OK on success, appropriate error otherwise.
*/
-bool element_stack_remove(hubbub_treebuilder *treebuilder, uint32_t index,
- hubbub_ns *ns, element_type *type, void **removed)
+hubbub_error element_stack_remove(hubbub_treebuilder *treebuilder,
+ uint32_t index, hubbub_ns *ns, element_type *type,
+ void **removed)
{
element_context *stack = treebuilder->context.element_stack;
uint32_t n;
@@ -1136,7 +1242,7 @@ bool element_stack_remove(hubbub_treebuilder *treebuilder, uint32_t index,
treebuilder->context.current_node--;
- return true;
+ return HUBBUB_OK;
}
/**
@@ -1193,9 +1299,9 @@ element_type prev_node(hubbub_treebuilder *treebuilder)
* \param type Type of node being inserted
* \param node Node being inserted
* \param stack_index Index into stack of open elements
- * \return True on success, false on memory exhaustion
+ * \return HUBBUB_OK on success, appropriate error otherwise
*/
-bool formatting_list_append(hubbub_treebuilder *treebuilder,
+hubbub_error formatting_list_append(hubbub_treebuilder *treebuilder,
hubbub_ns ns, element_type type, void *node,
uint32_t stack_index)
{
@@ -1204,7 +1310,7 @@ bool formatting_list_append(hubbub_treebuilder *treebuilder,
entry = treebuilder->alloc(NULL, sizeof(formatting_list_entry),
treebuilder->alloc_pw);
if (entry == NULL)
- return false;
+ return HUBBUB_NOMEM;
entry->details.ns = ns;
entry->details.type = type;
@@ -1221,7 +1327,7 @@ bool formatting_list_append(hubbub_treebuilder *treebuilder,
treebuilder->context.formatting_list_end = entry;
- return true;
+ return HUBBUB_OK;
}
/**
@@ -1234,9 +1340,9 @@ bool formatting_list_append(hubbub_treebuilder *treebuilder,
* \param type Type of node being inserted
* \param node Node being inserted
* \param stack_index Index into stack of open elements
- * \return True on success, false on memory exhaustion
+ * \return HUBBUB_OK on success, appropriate error otherwise
*/
-bool formatting_list_insert(hubbub_treebuilder *treebuilder,
+hubbub_error formatting_list_insert(hubbub_treebuilder *treebuilder,
formatting_list_entry *prev, formatting_list_entry *next,
hubbub_ns ns, element_type type, void *node,
uint32_t stack_index)
@@ -1254,7 +1360,7 @@ bool formatting_list_insert(hubbub_treebuilder *treebuilder,
entry = treebuilder->alloc(NULL, sizeof(formatting_list_entry),
treebuilder->alloc_pw);
if (entry == NULL)
- return false;
+ return HUBBUB_NOMEM;
entry->details.ns = ns;
entry->details.type = type;
@@ -1274,7 +1380,7 @@ bool formatting_list_insert(hubbub_treebuilder *treebuilder,
else
treebuilder->context.formatting_list_end = entry;
- return true;
+ return HUBBUB_OK;
}
@@ -1287,9 +1393,9 @@ bool formatting_list_insert(hubbub_treebuilder *treebuilder,
* \param type Pointer to location to receive type of node
* \param node Pointer to location to receive node
* \param stack_index Pointer to location to receive stack index
- * \return True on success, false on memory exhaustion
+ * \return HUBBUB_OK on success, appropriate error otherwise.
*/
-bool formatting_list_remove(hubbub_treebuilder *treebuilder,
+hubbub_error formatting_list_remove(hubbub_treebuilder *treebuilder,
formatting_list_entry *entry,
hubbub_ns *ns, element_type *type, void **node,
uint32_t *stack_index)
@@ -1311,7 +1417,7 @@ bool formatting_list_remove(hubbub_treebuilder *treebuilder,
treebuilder->alloc(entry, 0, treebuilder->alloc_pw);
- return true;
+ return HUBBUB_OK;
}
/**
@@ -1327,9 +1433,9 @@ bool formatting_list_remove(hubbub_treebuilder *treebuilder,
* \param otype Pointer to location to receive old type
* \param onode Pointer to location to receive old node
* \param ostack_index Pointer to location to receive old stack index
- * \return True on success, false on memory exhaustion
+ * \return HUBBUB_OK on success, appropriate error otherwise
*/
-bool formatting_list_replace(hubbub_treebuilder *treebuilder,
+hubbub_error formatting_list_replace(hubbub_treebuilder *treebuilder,
formatting_list_entry *entry,
hubbub_ns ns, element_type type, void *node,
uint32_t stack_index,
@@ -1348,7 +1454,7 @@ bool formatting_list_replace(hubbub_treebuilder *treebuilder,
entry->details.node = node;
entry->stack_index = stack_index;
- return true;
+ return HUBBUB_OK;
}