From 18e41840989de4f4705b4d56df7daa6ce7073491 Mon Sep 17 00:00:00 2001 From: Rupinder Singh Khokhar Date: Sun, 20 Jul 2014 12:35:25 +0530 Subject: Added support for template tag. However, the client currently doesn't support it. Hence, the only thing left to be done is to callback the client during insert_element, taking proper care of the template tags --- src/treebuilder/Makefile | 2 +- src/treebuilder/after_head.c | 5 ++- src/treebuilder/in_body.c | 69 +++++++++++++++++++++++---------------- src/treebuilder/in_column_group.c | 4 +++ src/treebuilder/in_head.c | 64 ++++++++++++++++++++++++++++++++++-- src/treebuilder/in_row.c | 3 +- src/treebuilder/in_select.c | 4 ++- src/treebuilder/in_table.c | 21 +++++------- src/treebuilder/in_table_body.c | 3 +- src/treebuilder/internal.h | 2 ++ src/treebuilder/modes.h | 3 ++ src/treebuilder/treebuilder.c | 66 ++++++++++++++++++++++++++++++++++--- 12 files changed, 193 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/treebuilder/Makefile b/src/treebuilder/Makefile index 31feae1..e48c0a9 100644 --- a/src/treebuilder/Makefile +++ b/src/treebuilder/Makefile @@ -6,6 +6,6 @@ DIR_SOURCES := treebuilder.c \ in_cell.c in_select.c in_select_in_table.c \ in_foreign_content.c after_body.c in_frameset.c \ after_frameset.c after_after_body.c after_after_frameset.c \ - generic_rcdata.c + in_template.c generic_rcdata.c include $(NSBUILD)/Makefile.subdir diff --git a/src/treebuilder/after_head.c b/src/treebuilder/after_head.c index f39299f..3a5d4c9 100644 --- a/src/treebuilder/after_head.c +++ b/src/treebuilder/after_head.c @@ -58,7 +58,8 @@ hubbub_error handle_after_head(hubbub_treebuilder *treebuilder, } else if (type == BASE || type == BASEFONT || type == BGSOUND || type == LINK || type == META || type == NOFRAMES || type == SCRIPT || - type == STYLE || type == TITLE) { + type == STYLE || type == TEMPLATE || + type == TITLE) { hubbub_ns ns; element_type otype; void *node; @@ -98,6 +99,8 @@ hubbub_error handle_after_head(hubbub_treebuilder *treebuilder, if (type == HTML || type == BODY || type == BR) { err = HUBBUB_REPROCESS; + } else if(type == TEMPLATE) { + err = handle_in_head(treebuilder, token); } else { /** \todo parse error */ } diff --git a/src/treebuilder/in_body.c b/src/treebuilder/in_body.c index bd73f08..ca2a34b 100644 --- a/src/treebuilder/in_body.c +++ b/src/treebuilder/in_body.c @@ -164,6 +164,12 @@ hubbub_error handle_in_body(hubbub_treebuilder *treebuilder, err = process_end_tag(treebuilder, token); break; case HUBBUB_TOKEN_EOF: + if (treebuilder->context.current_template_mode > -1) { + treebuilder->context.mode = + IN_TEMPLATE; + err = HUBBUB_REPROCESS; + break; + } for (i = treebuilder->context.current_node; i > 0; i--) { element_type type = @@ -211,7 +217,6 @@ hubbub_error process_character(hubbub_treebuilder *treebuilder, err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; - if (treebuilder->context.strip_leading_lr) { const uint8_t *str = dummy.ptr; @@ -267,7 +272,8 @@ hubbub_error process_start_tag(hubbub_treebuilder *treebuilder, err = process_html_in_body(treebuilder, token); } else if (type == BASE || type == BASEFONT || type == BGSOUND || type == LINK || type == META || type == NOFRAMES || - type == SCRIPT || type == STYLE || type == TITLE) { + type == SCRIPT || type == STYLE || type == TEMPLATE + || type == TITLE) { /* Process as "in head" */ err = handle_in_head(treebuilder, token); } else if (type == BODY) { @@ -519,6 +525,8 @@ hubbub_error process_end_tag(hubbub_treebuilder *treebuilder, (treebuilder->context.enable_scripting && type == NOSCRIPT)) { /** \todo parse error */ + } else if (type == TEMPLATE) { + err = handle_in_head(treebuilder, token); } else { err = process_0generic_in_body(treebuilder, type); } @@ -591,6 +599,9 @@ hubbub_error process_html_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { /** \todo parse error */ + if(template_in_stack(treebuilder)) + return HUBBUB_OK; + return add_attributes_stack(treebuilder, token, 0); } @@ -607,7 +618,8 @@ hubbub_error process_body_in_body(hubbub_treebuilder *treebuilder, /** \todo parse error */ if (treebuilder->context.current_node < 1 || - treebuilder->context.element_stack[1].type != BODY) + treebuilder->context.element_stack[1].type != BODY || + template_in_stack(treebuilder)) return HUBBUB_OK; treebuilder->context.frameset_ok = false; @@ -721,18 +733,10 @@ hubbub_error process_form_in_body(hubbub_treebuilder *treebuilder, { hubbub_error err; - element_context *stack = treebuilder->context.element_stack; - bool template_in_stack = false; - uint32_t n; - for (n = treebuilder->context.current_node; - n > 0; n--) { - if(stack[n].type == TEMPLATE) { - template_in_stack = true; - break; - } - } + bool in_stack = template_in_stack(treebuilder); + if (treebuilder->context.form_element != NULL && - template_in_stack == false) { + in_stack == false) { /** \todo parse error */ } else { if (element_in_scope(treebuilder, P, BUTTON_SCOPE)) { @@ -752,7 +756,7 @@ hubbub_error process_form_in_body(hubbub_treebuilder *treebuilder, treebuilder->context.element_stack[ treebuilder->context.current_node].node); - if(template_in_stack == false) { + if(in_stack == false) { treebuilder->context.form_element = treebuilder->context.element_stack[ treebuilder->context.current_node].node; @@ -1236,26 +1240,18 @@ hubbub_error process_isindex_in_body(hubbub_treebuilder *treebuilder, { hubbub_error err; hubbub_token dummy; - element_context *stack = treebuilder->context.element_stack; hubbub_attribute *action = NULL; hubbub_attribute *prompt = NULL; hubbub_attribute *attrs = NULL; size_t n_attrs = 0; - uint32_t n; - bool template_in_stack = false; + bool in_stack = template_in_stack( + treebuilder); hubbub_ns ns; void *node; element_type o_type; - for (n = treebuilder->context.current_node; - n > 0; n--) { - if(stack[n].type == TEMPLATE) { - template_in_stack = true; - break; - } - } - if (template_in_stack == false && + if (in_stack == false && treebuilder->context.form_element != NULL) return HUBBUB_OK; @@ -1592,6 +1588,22 @@ hubbub_error process_0form_in_body(hubbub_treebuilder *treebuilder) void *node = treebuilder->context.form_element; uint32_t idx = 0; + if(template_in_stack (treebuilder)) { + if(!element_in_scope(treebuilder, FORM, NONE)) { + /** \todo parse error */ + } else { + close_implied_end_tags(treebuilder, + UNKNOWN); + + if(current_node(treebuilder) != FORM) { + /** \todo parse error */ + } + element_stack_pop_until(treebuilder, + FORM); + } + return HUBBUB_OK; + } + if (treebuilder->context.form_element != NULL) treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, @@ -1600,8 +1612,7 @@ hubbub_error process_0form_in_body(hubbub_treebuilder *treebuilder) idx = element_in_scope(treebuilder, FORM, NONE); - if (idx == 0 || node == NULL || - treebuilder->context.element_stack[idx].node != node) { + if (idx == 0 || node == NULL) { /** \todo parse error */ } else { hubbub_ns ns; @@ -1616,7 +1627,7 @@ hubbub_error process_0form_in_body(hubbub_treebuilder *treebuilder) /** \todo parse error */ } - element_stack_remove(treebuilder, idx, + element_stack_remove(treebuilder, idx, &ns, &otype, &onode); treebuilder->tree_handler->unref_node( diff --git a/src/treebuilder/in_column_group.c b/src/treebuilder/in_column_group.c index 9436fc6..b69332b 100644 --- a/src/treebuilder/in_column_group.c +++ b/src/treebuilder/in_column_group.c @@ -53,6 +53,8 @@ hubbub_error handle_in_column_group(hubbub_treebuilder *treebuilder, false); /** \todo ack sc flag */ + } else if(type == TEMPLATE) { + err = handle_in_head(treebuilder, token); } else { err = HUBBUB_REPROCESS; } @@ -68,6 +70,8 @@ hubbub_error handle_in_column_group(hubbub_treebuilder *treebuilder, handled = true; } else if (type == COL) { /** \todo parse error */ + } else if(type == TEMPLATE) { + err = handle_in_head(treebuilder, token); } else { err = HUBBUB_REPROCESS; } diff --git a/src/treebuilder/in_head.c b/src/treebuilder/in_head.c index 52a2e3f..a10ba23 100644 --- a/src/treebuilder/in_head.c +++ b/src/treebuilder/in_head.c @@ -19,7 +19,6 @@ #include "utils/utils.h" #include "utils/string.h" - /** * Process a meta tag as if "in head". * @@ -164,6 +163,47 @@ hubbub_error handle_in_head(hubbub_treebuilder *treebuilder, err = parse_generic_rcdata(treebuilder, token, HUBBUB_CONTENT_MODEL_SCRIPTDATA); } else if (type == HEAD) { /** \todo parse error */ + } else if (type == TEMPLATE) { + err = insert_element(treebuilder, &token->data.tag, + true); + if (err != HUBBUB_OK) + return err; + + /* Insert a Marker */ + treebuilder->tree_handler->ref_node( + treebuilder->tree_handler->ctx, + treebuilder->context.element_stack[ + treebuilder->context.current_node].node); + + err = formatting_list_append(treebuilder, token->data.tag.ns, type, + treebuilder->context.element_stack[ + treebuilder->context.current_node].node, + token->data.tag.attributes, token->data.tag.n_attributes, + treebuilder->context.current_node); + if (err != HUBBUB_OK) { + hubbub_ns ns; + element_type type; + void *node; + remove_node_from_dom(treebuilder, + treebuilder->context.element_stack[ + treebuilder->context.current_node].node); + + element_stack_pop(treebuilder, &ns, &type, &node); + + /* 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; + treebuilder->context.mode = IN_TEMPLATE; + + err = template_stack_push(treebuilder, IN_TEMPLATE); } else { err = HUBBUB_REPROCESS; } @@ -176,9 +216,29 @@ hubbub_error handle_in_head(hubbub_treebuilder *treebuilder, if (type == HEAD) { handled = true; + } else if(type == TEMPLATE) { + /**todo parse error */ + if(!template_in_stack(treebuilder)) { + /** \todo parse error */ + break; + } + insertion_mode mode; + close_implied_end_tags_thorough(treebuilder); + + err = element_stack_pop_until(treebuilder, + TEMPLATE); + if (err != HUBBUB_OK) + return err; + + clear_active_formatting_list_to_marker( + treebuilder); + err = template_stack_pop (treebuilder, &mode); + reset_insertion_mode (treebuilder); } else if (type == HTML || type == BODY || type == BR) { err = HUBBUB_REPROCESS; - } /** \todo parse error */ + } else { + /** \todo parse error */ + } } break; case HUBBUB_TOKEN_EOF: diff --git a/src/treebuilder/in_row.c b/src/treebuilder/in_row.c index 0446e6f..c31d826 100644 --- a/src/treebuilder/in_row.c +++ b/src/treebuilder/in_row.c @@ -23,7 +23,8 @@ static void table_clear_stack(hubbub_treebuilder *treebuilder) { element_type cur_node = current_node(treebuilder); - while (cur_node != TR && cur_node != HTML) { + while (cur_node != TR && cur_node != TEMPLATE && + cur_node != HTML) { hubbub_ns ns; element_type type; void *node; diff --git a/src/treebuilder/in_select.c b/src/treebuilder/in_select.c index 7675dc5..c3db89d 100644 --- a/src/treebuilder/in_select.c +++ b/src/treebuilder/in_select.c @@ -100,7 +100,7 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder, if (type != SELECT) err = HUBBUB_REPROCESS; - } else if (type == SCRIPT) { + } else if (type == SCRIPT || type == TEMPLATE) { err = handle_in_head(treebuilder, token); } else { /** \todo parse error */ @@ -153,6 +153,8 @@ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder, /* fragment case */ /** \todo parse error */ } + } else if (type == TEMPLATE) { + err = handle_in_head(treebuilder, token); } } break; diff --git a/src/treebuilder/in_table.c b/src/treebuilder/in_table.c index cf61827..03dc4f7 100644 --- a/src/treebuilder/in_table.c +++ b/src/treebuilder/in_table.c @@ -26,7 +26,7 @@ static inline void clear_stack_table_context(hubbub_treebuilder *treebuilder) element_type type = current_node(treebuilder); void *node; - while (type != TABLE && type != HTML) { + while (type != TABLE && type != HTML && type != TEMPLATE) { element_stack_pop(treebuilder, &ns, &type, &node); treebuilder->tree_handler->unref_node( @@ -208,23 +208,16 @@ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder, reset_insertion_mode(treebuilder); err = HUBBUB_REPROCESS; - } else if (type == STYLE || type == SCRIPT) { + } else if (type == STYLE || type == SCRIPT || + type == TEMPLATE) { err = handle_in_head(treebuilder, token); } else if (type == INPUT) { err = process_input_in_table(treebuilder, token); handled = (err == HUBBUB_OK); } else if(type == FORM) { - element_context *stack = treebuilder->context.element_stack; - bool template_in_stack = false; - uint32_t n; - for (n = treebuilder->context.current_node; - n > 0; n--) { - if(stack[n].type == TEMPLATE) { - template_in_stack = true; - break; - } - } - if(template_in_stack == true || + bool in_stack = template_in_stack(treebuilder); + + if(in_stack == true || treebuilder->context.form_element != NULL ) { /* ignore the token*/ break; @@ -268,6 +261,8 @@ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder, type == TBODY || type == TD || type == TFOOT || type == TH || type == THEAD || type == TR) { /** \todo parse error */ + } else if (type == TEMPLATE) { + err = handle_in_head(treebuilder, token); } else { handled = false; } diff --git a/src/treebuilder/in_table_body.c b/src/treebuilder/in_table_body.c index c8c26cf..e6fbcc3 100644 --- a/src/treebuilder/in_table_body.c +++ b/src/treebuilder/in_table_body.c @@ -24,7 +24,8 @@ static void table_clear_stack(hubbub_treebuilder *treebuilder) element_type cur_node = current_node(treebuilder); while (cur_node != TBODY && cur_node != TFOOT && - cur_node != THEAD && cur_node != HTML) { + cur_node != THEAD && cur_node != HTML && + cur_node != TEMPLATE) { hubbub_ns ns; element_type type; void *node; diff --git a/src/treebuilder/internal.h b/src/treebuilder/internal.h index de371b0..18a34bd 100644 --- a/src/treebuilder/internal.h +++ b/src/treebuilder/internal.h @@ -166,6 +166,7 @@ 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 close_implied_end_tags_thorough(hubbub_treebuilder *treebuilder); void reset_insertion_mode(hubbub_treebuilder *treebuilder); hubbub_error append_text(hubbub_treebuilder *treebuilder, const hubbub_string *string); @@ -224,6 +225,7 @@ bool is_mathml_text_integration (element_type type, bool is_html_integration (element_type type, hubbub_ns ns, hubbub_attribute *attrs, size_t n_attrs); +bool template_in_stack (hubbub_treebuilder *treebuilder); /* in_foreign_content.c */ void adjust_mathml_attributes(hubbub_treebuilder *treebuilder, hubbub_tag *tag); diff --git a/src/treebuilder/modes.h b/src/treebuilder/modes.h index 411e7a6..eefe18e 100644 --- a/src/treebuilder/modes.h +++ b/src/treebuilder/modes.h @@ -34,6 +34,7 @@ typedef enum AFTER_FRAMESET, AFTER_AFTER_BODY, AFTER_AFTER_FRAMESET, + IN_TEMPLATE, GENERIC_RCDATA } insertion_mode; @@ -86,5 +87,7 @@ hubbub_error handle_after_after_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_after_after_frameset(hubbub_treebuilder *treebuilder, const hubbub_token *token); +hubbub_error handle_in_template(hubbub_treebuilder *treebuilder, + const hubbub_token *token); #endif diff --git a/src/treebuilder/treebuilder.c b/src/treebuilder/treebuilder.c index 8f0e7e3..9cc4b12 100644 --- a/src/treebuilder/treebuilder.c +++ b/src/treebuilder/treebuilder.c @@ -389,6 +389,9 @@ hubbub_error hubbub_treebuilder_token_handler(const hubbub_token *token, mode(AFTER_AFTER_FRAMESET) err = handle_after_after_frameset(treebuilder, token); break; + mode(IN_TEMPLATE) + err = handle_in_template(treebuilder, token); + break; mode(GENERIC_RCDATA) err = handle_generic_rcdata(treebuilder, token); break; @@ -934,11 +937,11 @@ hubbub_error insert_element(hubbub_treebuilder *treebuilder, } /** - * Close implied end tags + * close implied end tags * - * \param treebuilder The treebuilder instance - * \param except Tag type to exclude from processing [DD,DT,LI,OPTION, - * OPTGROUP,P,RP,RT], UNKNOWN to exclude nothing + * \param treebuilder the treebuilder instance + * \param except tag type to exclude from processing [dd,dt,li,option, + * optgroup,p,rp,rt], unknown to exclude nothing */ void close_implied_end_tags(hubbub_treebuilder *treebuilder, element_type except) @@ -969,6 +972,39 @@ void close_implied_end_tags(hubbub_treebuilder *treebuilder, } } +/** + * close implied end tags "thoroughly" + * + * \param treebuilder the treebuilder instance + */ +void close_implied_end_tags_thorough(hubbub_treebuilder *treebuilder) +{ + element_type type; + + type = treebuilder->context.element_stack[ + treebuilder->context.current_node].type; + + while(type == CAPTION || type == COLGROUP || type == DD || + type == DT || type == LI || type == OPTION || + type == OPTGROUP || type == P || type == RP || + type == RT || type == TBODY || type == TD || + type ==TFOOT || type == TH || + type == THEAD || type == TR) { + hubbub_ns ns; + element_type otype; + void *node; + + element_stack_pop(treebuilder, &ns, &otype, &node); + + treebuilder->tree_handler->unref_node( + treebuilder->tree_handler->ctx, + node); + + type = treebuilder->context.element_stack[ + treebuilder->context.current_node].type; + } +} + /** * Reset the insertion mode * @@ -1027,6 +1063,11 @@ void reset_insertion_mode(hubbub_treebuilder *treebuilder) case TABLE: treebuilder->context.mode = IN_TABLE; return; + case TEMPLATE: + treebuilder->context.mode = + treebuilder->context.template_stack[ + treebuilder->context.current_template_mode]; + return; case HEAD: /* fragment case */ treebuilder->context.mode = IN_HEAD; @@ -1820,6 +1861,23 @@ bool is_html_integration (element_type type, return false; } +/** + * Check whether the stack of open elements has a template element + * + * \param treebuilder The treebuilder instance + */ +bool template_in_stack (hubbub_treebuilder *treebuilder) { + uint32_t i; + element_context* stack = + treebuilder->context.element_stack; + for(i = treebuilder->context.current_node; i > 0; + i--) { + if(stack[i].type == TEMPLATE) { + return true; + } + } + return false; +} #ifndef NDEBUG /** -- cgit v1.2.3