OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. |
3 * Copyright (C) 2011 Apple Inc. All rights reserved. | 3 * Copyright (C) 2011 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
670 | 670 |
671 void HTMLConstructionSite::InsertCommentOnHTMLHtmlElement( | 671 void HTMLConstructionSite::InsertCommentOnHTMLHtmlElement( |
672 AtomicHTMLToken* token) { | 672 AtomicHTMLToken* token) { |
673 DCHECK_EQ(token->GetType(), HTMLToken::kComment); | 673 DCHECK_EQ(token->GetType(), HTMLToken::kComment); |
674 ContainerNode* parent = open_elements_.RootNode(); | 674 ContainerNode* parent = open_elements_.RootNode(); |
675 AttachLater(parent, Comment::Create(parent->GetDocument(), token->Comment())); | 675 AttachLater(parent, Comment::Create(parent->GetDocument(), token->Comment())); |
676 } | 676 } |
677 | 677 |
678 void HTMLConstructionSite::InsertHTMLHeadElement(AtomicHTMLToken* token) { | 678 void HTMLConstructionSite::InsertHTMLHeadElement(AtomicHTMLToken* token) { |
679 DCHECK(!ShouldFosterParent()); | 679 DCHECK(!ShouldFosterParent()); |
680 head_ = HTMLStackItem::Create(CreateHTMLElement(token), token); | 680 head_ = HTMLStackItem::Create(CreateElement(token, xhtmlNamespaceURI), token); |
681 AttachLater(CurrentNode(), head_->GetElement()); | 681 AttachLater(CurrentNode(), head_->GetElement()); |
682 open_elements_.PushHTMLHeadElement(head_); | 682 open_elements_.PushHTMLHeadElement(head_); |
683 } | 683 } |
684 | 684 |
685 void HTMLConstructionSite::InsertHTMLBodyElement(AtomicHTMLToken* token) { | 685 void HTMLConstructionSite::InsertHTMLBodyElement(AtomicHTMLToken* token) { |
686 DCHECK(!ShouldFosterParent()); | 686 DCHECK(!ShouldFosterParent()); |
687 HTMLElement* body = CreateHTMLElement(token); | 687 Element* body = CreateElement(token, xhtmlNamespaceURI); |
688 AttachLater(CurrentNode(), body); | 688 AttachLater(CurrentNode(), body); |
689 open_elements_.PushHTMLBodyElement(HTMLStackItem::Create(body, token)); | 689 open_elements_.PushHTMLBodyElement(HTMLStackItem::Create(body, token)); |
690 if (document_) | 690 if (document_) |
691 document_->WillInsertBody(); | 691 document_->WillInsertBody(); |
692 } | 692 } |
693 | 693 |
694 void HTMLConstructionSite::InsertHTMLFormElement(AtomicHTMLToken* token, | 694 void HTMLConstructionSite::InsertHTMLFormElement(AtomicHTMLToken* token, |
695 bool is_demoted) { | 695 bool is_demoted) { |
696 HTMLElement* element = CreateHTMLElement(token); | 696 Element* element = CreateElement(token, xhtmlNamespaceURI); |
697 DCHECK(isHTMLFormElement(element)); | 697 DCHECK(isHTMLFormElement(element)); |
698 HTMLFormElement* form_element = toHTMLFormElement(element); | 698 HTMLFormElement* form_element = toHTMLFormElement(element); |
699 if (!OpenElements()->HasTemplateInHTMLScope()) | 699 if (!OpenElements()->HasTemplateInHTMLScope()) |
700 form_ = form_element; | 700 form_ = form_element; |
701 form_element->SetDemoted(is_demoted); | 701 form_element->SetDemoted(is_demoted); |
702 AttachLater(CurrentNode(), form_element); | 702 AttachLater(CurrentNode(), form_element); |
703 open_elements_.Push(HTMLStackItem::Create(form_element, token)); | 703 open_elements_.Push(HTMLStackItem::Create(form_element, token)); |
704 } | 704 } |
705 | 705 |
706 void HTMLConstructionSite::InsertHTMLElement(AtomicHTMLToken* token) { | 706 void HTMLConstructionSite::InsertHTMLElement(AtomicHTMLToken* token) { |
707 HTMLElement* element = CreateHTMLElement(token); | 707 Element* element = CreateElement(token, xhtmlNamespaceURI); |
708 AttachLater(CurrentNode(), element); | 708 AttachLater(CurrentNode(), element); |
709 open_elements_.Push(HTMLStackItem::Create(element, token)); | 709 open_elements_.Push(HTMLStackItem::Create(element, token)); |
710 } | 710 } |
711 | 711 |
712 void HTMLConstructionSite::InsertSelfClosingHTMLElementDestroyingToken( | 712 void HTMLConstructionSite::InsertSelfClosingHTMLElementDestroyingToken( |
713 AtomicHTMLToken* token) { | 713 AtomicHTMLToken* token) { |
714 DCHECK_EQ(token->GetType(), HTMLToken::kStartTag); | 714 DCHECK_EQ(token->GetType(), HTMLToken::kStartTag); |
715 // Normally HTMLElementStack is responsible for calling finishParsingChildren, | 715 // Normally HTMLElementStack is responsible for calling finishParsingChildren, |
716 // but self-closing elements are never in the element stack so the stack | 716 // but self-closing elements are never in the element stack so the stack |
717 // doesn't get a chance to tell them that we're done parsing their children. | 717 // doesn't get a chance to tell them that we're done parsing their children. |
718 AttachLater(CurrentNode(), CreateHTMLElement(token), true); | 718 AttachLater(CurrentNode(), CreateElement(token, xhtmlNamespaceURI), true); |
719 // FIXME: Do we want to acknowledge the token's self-closing flag? | 719 // FIXME: Do we want to acknowledge the token's self-closing flag? |
720 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.ht ml#acknowledge-self-closing-flag | 720 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.ht ml#acknowledge-self-closing-flag |
721 } | 721 } |
722 | 722 |
723 void HTMLConstructionSite::InsertFormattingElement(AtomicHTMLToken* token) { | 723 void HTMLConstructionSite::InsertFormattingElement(AtomicHTMLToken* token) { |
724 // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#th e-stack-of-open-elements | 724 // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#th e-stack-of-open-elements |
725 // Possible active formatting elements include: | 725 // Possible active formatting elements include: |
726 // a, b, big, code, em, font, i, nobr, s, small, strike, strong, tt, and u. | 726 // a, b, big, code, em, font, i, nobr, s, small, strike, strong, tt, and u. |
727 InsertHTMLElement(token); | 727 InsertHTMLElement(token); |
728 active_formatting_elements_.Append(CurrentElementRecord()->StackItem()); | 728 active_formatting_elements_.Append(CurrentElementRecord()->StackItem()); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
835 HTMLConstructionSiteTask task(HTMLConstructionSiteTask::kTakeAllChildren); | 835 HTMLConstructionSiteTask task(HTMLConstructionSiteTask::kTakeAllChildren); |
836 task.parent = new_parent->GetNode(); | 836 task.parent = new_parent->GetNode(); |
837 task.child = old_parent->GetNode(); | 837 task.child = old_parent->GetNode(); |
838 QueueTask(task); | 838 QueueTask(task); |
839 } | 839 } |
840 | 840 |
841 CreateElementFlags HTMLConstructionSite::GetCreateElementFlags() const { | 841 CreateElementFlags HTMLConstructionSite::GetCreateElementFlags() const { |
842 return is_parsing_fragment_ ? kCreatedByFragmentParser : kCreatedByParser; | 842 return is_parsing_fragment_ ? kCreatedByFragmentParser : kCreatedByParser; |
843 } | 843 } |
844 | 844 |
845 Element* HTMLConstructionSite::CreateElement( | |
846 AtomicHTMLToken* token, | |
847 const AtomicString& namespace_uri) { | |
848 QualifiedName tag_name(g_null_atom, token->GetName(), namespace_uri); | |
849 Element* element = OwnerDocumentForCurrentNode().createElement( | |
850 tag_name, GetCreateElementFlags()); | |
851 SetAttributes(element, token, parser_content_policy_); | |
852 return element; | |
853 } | |
854 | |
855 inline Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() { | 845 inline Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() { |
856 if (isHTMLTemplateElement(*CurrentNode())) | 846 if (isHTMLTemplateElement(*CurrentNode())) |
857 return toHTMLTemplateElement(CurrentElement())->content()->GetDocument(); | 847 return toHTMLTemplateElement(CurrentElement())->content()->GetDocument(); |
858 return CurrentNode()->GetDocument(); | 848 return CurrentNode()->GetDocument(); |
859 } | 849 } |
860 | 850 |
861 // "look up a custom element definition" for a token | 851 // "look up a custom element definition" for a token |
862 // https://html.spec.whatwg.org/#look-up-a-custom-element-definition | 852 // https://html.spec.whatwg.org/#look-up-a-custom-element-definition |
863 CustomElementDefinition* HTMLConstructionSite::LookUpCustomElementDefinition( | 853 CustomElementDefinition* HTMLConstructionSite::LookUpCustomElementDefinition( |
864 Document& document, | 854 Document& document, |
(...skipping 13 matching lines...) Expand all Loading... | |
878 const Attribute* is_attribute = token->GetAttributeItem(HTMLNames::isAttr); | 868 const Attribute* is_attribute = token->GetAttributeItem(HTMLNames::isAttr); |
879 const AtomicString& name = is_attribute ? is_attribute->Value() : local_name; | 869 const AtomicString& name = is_attribute ? is_attribute->Value() : local_name; |
880 CustomElementDescriptor descriptor(name, local_name); | 870 CustomElementDescriptor descriptor(name, local_name); |
881 | 871 |
882 // 4.-6. | 872 // 4.-6. |
883 return registry->DefinitionFor(descriptor); | 873 return registry->DefinitionFor(descriptor); |
884 } | 874 } |
885 | 875 |
886 // "create an element for a token" | 876 // "create an element for a token" |
887 // https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for-the- token | 877 // https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for-the- token |
888 // TODO(dominicc): When form association is separate from creation, unify this | 878 Element* HTMLConstructionSite::CreateElement( |
889 // with foreign element creation. Add a namespace parameter and check for HTML | 879 AtomicHTMLToken* token, |
890 // namespace to lookupCustomElementDefinition. | 880 const AtomicString& namespace_uri) { |
891 HTMLElement* HTMLConstructionSite::CreateHTMLElement(AtomicHTMLToken* token) { | |
892 // "1. Let document be intended parent's node document." | 881 // "1. Let document be intended parent's node document." |
893 Document& document = OwnerDocumentForCurrentNode(); | 882 Document& document = OwnerDocumentForCurrentNode(); |
894 | 883 |
895 // Only associate the element with the current form if we're creating the new | |
896 // element in a document with a browsing context (rather than in <template> | |
897 // contents). | |
898 // TODO(dominicc): Change form to happen after element creation when | |
899 // implementing customized built-in elements. | |
900 HTMLFormElement* form = document.GetFrame() ? form_.Get() : nullptr; | |
901 | |
902 // "2. Let local name be the tag name of the token." | 884 // "2. Let local name be the tag name of the token." |
903 // "3. Let is be the value of the "is" attribute in the giev token ..." etc. | 885 QualifiedName tag_name(g_null_atom, token->GetName(), namespace_uri); |
886 // "3. Let is be the value of the "is" attribute in the given token ..." etc. | |
904 // "4. Let definition be the result of looking up a custom element ..." etc. | 887 // "4. Let definition be the result of looking up a custom element ..." etc. |
905 CustomElementDefinition* definition = | 888 CustomElementDefinition* definition = |
906 is_parsing_fragment_ ? nullptr | 889 is_parsing_fragment_ ? nullptr |
907 : LookUpCustomElementDefinition(document, token); | 890 : LookUpCustomElementDefinition(document, token); |
908 // "5. If definition is non-null and the parser was not originally created | 891 // "5. If definition is non-null and the parser was not originally created |
909 // for the HTML fragment parsing algorithm, then let will execute script | 892 // for the HTML fragment parsing algorithm, then let will execute script |
910 // be true." | 893 // be true." |
911 bool will_execute_script = definition && !is_parsing_fragment_; | 894 bool will_execute_script = definition && !is_parsing_fragment_; |
912 | 895 |
913 HTMLElement* element; | 896 Element* element; |
914 | 897 |
915 if (will_execute_script) { | 898 if (will_execute_script) { |
916 // "6.1 Increment the document's throw-on-dynamic-insertion counter." | 899 // "6.1 Increment the document's throw-on-dynamic-insertion counter." |
917 ThrowOnDynamicMarkupInsertionCountIncrementer | 900 ThrowOnDynamicMarkupInsertionCountIncrementer |
918 throw_on_dynamic_markup_insertions(&document); | 901 throw_on_dynamic_markup_insertions(&document); |
919 | 902 |
920 // "6.2 If the JavaScript execution context stack is empty, | 903 // "6.2 If the JavaScript execution context stack is empty, |
921 // then perform a microtask checkpoint." | 904 // then perform a microtask checkpoint." |
922 | 905 |
923 // TODO(dominicc): This is the way the Blink HTML parser performs | 906 // TODO(dominicc): This is the way the Blink HTML parser performs |
924 // checkpoints, but note the spec is different--it talks about the | 907 // checkpoints, but note the spec is different--it talks about the |
925 // JavaScript stack, not the script nesting level. | 908 // JavaScript stack, not the script nesting level. |
926 if (0u == reentry_permit_->ScriptNestingLevel()) | 909 if (0u == reentry_permit_->ScriptNestingLevel()) |
927 Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate()); | 910 Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate()); |
928 | 911 |
929 // "6.3 Push a new element queue onto the custom element | 912 // "6.3 Push a new element queue onto the custom element |
930 // reactions stack." | 913 // reactions stack." |
931 CEReactionsScope reactions; | 914 CEReactionsScope reactions; |
932 | 915 |
933 // 7. | 916 // 7. |
934 QualifiedName element_q_name(g_null_atom, token->GetName(), | 917 element = definition->CreateElementSync(document, tag_name); |
935 HTMLNames::xhtmlNamespaceURI); | |
936 element = definition->CreateElementSync(document, element_q_name); | |
937 | 918 |
938 // "8. Append each attribute in the given token to element." We don't use | 919 // "8. Append each attribute in the given token to element." We don't use |
939 // setAttributes here because the custom element constructor may have | 920 // setAttributes here because the custom element constructor may have |
940 // manipulated attributes. | 921 // manipulated attributes. |
941 for (const auto& attribute : token->Attributes()) | 922 for (const auto& attribute : token->Attributes()) |
942 element->setAttribute(attribute.GetName(), attribute.Value()); | 923 element->setAttribute(attribute.GetName(), attribute.Value()); |
943 | 924 |
944 // "9. If will execute script is true, then ..." etc. The CEReactionsScope | 925 // "9. If will execute script is true, then ..." etc. The CEReactionsScope |
945 // and ThrowOnDynamicMarkupInsertionCountIncrementer destructors implement | 926 // and ThrowOnDynamicMarkupInsertionCountIncrementer destructors implement |
946 // steps 9.1-3. | 927 // steps 9.1-3. |
947 } else { | 928 } else { |
948 // FIXME: This can't use HTMLConstructionSite::createElement because we have | 929 element = document.createElement(tag_name, GetCreateElementFlags()); |
949 // to pass the current form element. We should rework form association to | |
950 // occur after construction to allow better code sharing here. | |
951 element = HTMLElementFactory::createHTMLElement(token->GetName(), document, | |
952 GetCreateElementFlags()); | |
953 if (FormAssociated* form_associated_element = | |
954 element->ToFormAssociatedOrNull()) { | |
955 form_associated_element->AssociateWith(form); | |
956 } | |
957 // Definition for the created element does not exist here and it cannot be | 930 // Definition for the created element does not exist here and it cannot be |
958 // custom or failed. | 931 // custom or failed. |
959 DCHECK_NE(element->GetCustomElementState(), CustomElementState::kCustom); | 932 DCHECK_NE(element->GetCustomElementState(), CustomElementState::kCustom); |
960 DCHECK_NE(element->GetCustomElementState(), CustomElementState::kFailed); | 933 DCHECK_NE(element->GetCustomElementState(), CustomElementState::kFailed); |
961 | 934 |
935 // TODO(dominicc): Move these steps so they happen for custom | |
936 // elements as well as built-in elements when customized built in | |
937 // elements are implemented for resettable, listed elements. | |
938 | |
939 // 10. If element has an xmlns attribute in the XMLNS namespace | |
940 // whose value is not exactly the same as the element's namespace, | |
941 // that is a parse error. Similarly, if element has an xmlns:xlink | |
942 // attribute in the XMLNS namespace whose value is not the XLink | |
943 // Namespace, that is a parse error. | |
944 | |
945 // TODO(dominicc): Implement step 10 when the HTML parser does | |
946 // something useful with parse errors. | |
kouhei (in TOK)
2017/04/26 04:24:54
FYI: I think we are going to ignore all parse erro
| |
947 | |
948 // 11. If element is a resettable element, invoke its reset | |
949 // algorithm. (This initializes the element's value and | |
950 // checkedness based on the element's attributes.) | |
951 // TODO(dominicc): Implement step 11, resettable elements. | |
952 | |
953 // 12. If element is a form-associated element, and the form | |
954 // element pointer is not null, and there is no template element | |
955 // on the stack of open elements, ... | |
956 FormAssociated* form_associated_element = | |
957 element->IsHTMLElement() | |
958 ? ToHTMLElement(element)->ToFormAssociatedOrNull() | |
959 : nullptr; | |
960 if (form_associated_element && document.GetFrame() && form_.Get()) { | |
961 // ... and element is either not listed or doesn't have a form | |
962 // attribute, and the intended parent is in the same tree as the | |
963 // element pointed to by the form element pointer, associate | |
964 // element with the form element pointed to by the form element | |
965 // pointer, and suppress the running of the reset the form owner | |
966 // algorithm when the parser subsequently attempts to insert the | |
967 // element. | |
968 | |
969 // TODO(dominicc): There are many differences to the spec here; | |
970 // some of them are observable: | |
971 // | |
972 // - The HTML spec tracks whether there is a template element on | |
973 // the stack both for manipulating the form element pointer | |
974 // and using it here. | |
975 // - FormAssociated::AssociateWith implementations don't do the | |
976 // "same tree" check; for example | |
977 // HTMLImageElement::AssociateWith just checks whether the form | |
978 // is in *a* tree. This check should be done here consistently. | |
979 // - ListedElement is a mixin; add IsListedElement and skip | |
980 // setting the form for listed attributes with form=. Instead | |
981 // we set attributes (step 8) out of order, after this step, | |
982 // to reset the form association. | |
983 form_associated_element->AssociateWith(form_.Get()); | |
984 } | |
962 // "8. Append each attribute in the given token to element." | 985 // "8. Append each attribute in the given token to element." |
963 SetAttributes(element, token, parser_content_policy_); | 986 SetAttributes(element, token, parser_content_policy_); |
964 } | 987 } |
965 | 988 |
966 // TODO(dominicc): Implement steps 10-12 when customized built-in elements are | |
967 // implemented. | |
968 | |
969 return element; | 989 return element; |
970 } | 990 } |
971 | 991 |
972 HTMLStackItem* HTMLConstructionSite::CreateElementFromSavedToken( | 992 HTMLStackItem* HTMLConstructionSite::CreateElementFromSavedToken( |
973 HTMLStackItem* item) { | 993 HTMLStackItem* item) { |
974 Element* element; | 994 Element* element; |
975 // NOTE: Moving from item -> token -> item copies the Attribute vector twice! | 995 // NOTE: Moving from item -> token -> item copies the Attribute vector twice! |
976 AtomicHTMLToken fake_token(HTMLToken::kStartTag, item->LocalName(), | 996 AtomicHTMLToken fake_token(HTMLToken::kStartTag, item->LocalName(), |
977 item->Attributes()); | 997 item->Attributes()); |
978 if (item->NamespaceURI() == HTMLNames::xhtmlNamespaceURI) | 998 element = CreateElement(&fake_token, item->NamespaceURI()); |
979 element = CreateHTMLElement(&fake_token); | |
980 else | |
981 element = CreateElement(&fake_token, item->NamespaceURI()); | |
982 return HTMLStackItem::Create(element, &fake_token, item->NamespaceURI()); | 999 return HTMLStackItem::Create(element, &fake_token, item->NamespaceURI()); |
983 } | 1000 } |
984 | 1001 |
985 bool HTMLConstructionSite::IndexOfFirstUnopenFormattingElement( | 1002 bool HTMLConstructionSite::IndexOfFirstUnopenFormattingElement( |
986 unsigned& first_unopen_element_index) const { | 1003 unsigned& first_unopen_element_index) const { |
987 if (active_formatting_elements_.IsEmpty()) | 1004 if (active_formatting_elements_.IsEmpty()) |
988 return false; | 1005 return false; |
989 unsigned index = active_formatting_elements_.size(); | 1006 unsigned index = active_formatting_elements_.size(); |
990 do { | 1007 do { |
991 --index; | 1008 --index; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1084 DCHECK(task.parent); | 1101 DCHECK(task.parent); |
1085 QueueTask(task); | 1102 QueueTask(task); |
1086 } | 1103 } |
1087 | 1104 |
1088 DEFINE_TRACE(HTMLConstructionSite::PendingText) { | 1105 DEFINE_TRACE(HTMLConstructionSite::PendingText) { |
1089 visitor->Trace(parent); | 1106 visitor->Trace(parent); |
1090 visitor->Trace(next_child); | 1107 visitor->Trace(next_child); |
1091 } | 1108 } |
1092 | 1109 |
1093 } // namespace blink | 1110 } // namespace blink |
OLD | NEW |