Chromium Code Reviews| 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 |