| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All |
| 7 * rights reserved. | 7 * rights reserved. |
| 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. | 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
| 9 * (http://www.torchmobile.com/) | 9 * (http://www.torchmobile.com/) |
| 10 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. | 10 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 // rule (d) above | 368 // rule (d) above |
| 369 WTF::Unicode::CharDecompositionType decomp_type = | 369 WTF::Unicode::CharDecompositionType decomp_type = |
| 370 WTF::Unicode::DecompositionType(c); | 370 WTF::Unicode::DecompositionType(c); |
| 371 if (decomp_type == WTF::Unicode::kDecompositionFont || | 371 if (decomp_type == WTF::Unicode::kDecompositionFont || |
| 372 decomp_type == WTF::Unicode::kDecompositionCompat) | 372 decomp_type == WTF::Unicode::kDecompositionCompat) |
| 373 return false; | 373 return false; |
| 374 | 374 |
| 375 return true; | 375 return true; |
| 376 } | 376 } |
| 377 | 377 |
| 378 // Tests whether |name| is something the HTML parser would accept as a |
| 379 // tag name. |
| 380 template <typename CharType> |
| 381 static inline bool IsValidElementNamePerHTMLParser(const CharType* characters, |
| 382 unsigned length) { |
| 383 CharType c = characters[0] | 0x20; |
| 384 if (!('a' <= c && c < 'z')) |
| 385 return false; |
| 386 |
| 387 for (unsigned i = 1; i < length; ++i) { |
| 388 c = characters[i]; |
| 389 if (c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == ' ' || |
| 390 c == '/' || c == '>') |
| 391 return false; |
| 392 } |
| 393 |
| 394 return true; |
| 395 } |
| 396 |
| 397 static bool IsValidElementNamePerHTMLParser(const String& name) { |
| 398 unsigned length = name.length(); |
| 399 if (!length) |
| 400 return false; |
| 401 |
| 402 if (name.Is8Bit()) { |
| 403 const LChar* characters = name.Characters8(); |
| 404 return IsValidElementNamePerHTMLParser(characters, length); |
| 405 } |
| 406 const UChar* characters = name.Characters16(); |
| 407 return IsValidElementNamePerHTMLParser(characters, length); |
| 408 } |
| 409 |
| 410 // Tests whether |name| is a valid name per DOM spec. Also checks |
| 411 // whether the HTML parser would accept this element name and counts |
| 412 // cases of mismatches. |
| 413 static bool IsValidElementName(const LocalDOMWindow* window, |
| 414 const String& name) { |
| 415 bool is_valid_dom_name = Document::IsValidName(name); |
| 416 bool is_valid_html_name = IsValidElementNamePerHTMLParser(name); |
| 417 if (UNLIKELY(is_valid_html_name != is_valid_dom_name && window)) { |
| 418 UseCounter::Count(window->GetFrame(), |
| 419 is_valid_dom_name |
| 420 ? UseCounter::kElementNameDOMValidHTMLParserInvalid |
| 421 : UseCounter::kElementNameDOMInvalidHTMLParserValid); |
| 422 } |
| 423 return is_valid_dom_name; |
| 424 } |
| 425 |
| 378 static bool AcceptsEditingFocus(const Element& element) { | 426 static bool AcceptsEditingFocus(const Element& element) { |
| 379 DCHECK(HasEditableStyle(element)); | 427 DCHECK(HasEditableStyle(element)); |
| 380 | 428 |
| 381 return element.GetDocument().GetFrame() && RootEditableElement(element); | 429 return element.GetDocument().GetFrame() && RootEditableElement(element); |
| 382 } | 430 } |
| 383 | 431 |
| 384 uint64_t Document::global_tree_version_ = 0; | 432 uint64_t Document::global_tree_version_ = 0; |
| 385 | 433 |
| 386 static bool g_threaded_parsing_enabled_for_testing = true; | 434 static bool g_threaded_parsing_enabled_for_testing = true; |
| 387 | 435 |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 | 735 |
| 688 bool Document::IsInMainFrame() const { | 736 bool Document::IsInMainFrame() const { |
| 689 return GetFrame() && GetFrame()->IsMainFrame(); | 737 return GetFrame() && GetFrame()->IsMainFrame(); |
| 690 } | 738 } |
| 691 | 739 |
| 692 AtomicString Document::ConvertLocalName(const AtomicString& name) { | 740 AtomicString Document::ConvertLocalName(const AtomicString& name) { |
| 693 return IsHTMLDocument() ? name.LowerASCII() : name; | 741 return IsHTMLDocument() ? name.LowerASCII() : name; |
| 694 } | 742 } |
| 695 | 743 |
| 696 // https://dom.spec.whatwg.org/#dom-document-createelement | 744 // https://dom.spec.whatwg.org/#dom-document-createelement |
| 697 Element* Document::createElement(const AtomicString& name, | 745 Element* Document::createElement(const LocalDOMWindow* window, |
| 746 const AtomicString& name, |
| 698 ExceptionState& exception_state) { | 747 ExceptionState& exception_state) { |
| 699 if (!IsValidName(name)) { | 748 if (!IsValidElementName(window, name)) { |
| 700 exception_state.ThrowDOMException( | 749 exception_state.ThrowDOMException( |
| 701 kInvalidCharacterError, | 750 kInvalidCharacterError, |
| 702 "The tag name provided ('" + name + "') is not a valid name."); | 751 "The tag name provided ('" + name + "') is not a valid name."); |
| 703 return nullptr; | 752 return nullptr; |
| 704 } | 753 } |
| 705 | 754 |
| 706 if (IsXHTMLDocument() || IsHTMLDocument()) { | 755 if (IsXHTMLDocument() || IsHTMLDocument()) { |
| 707 // 2. If the context object is an HTML document, let localName be | 756 // 2. If the context object is an HTML document, let localName be |
| 708 // converted to ASCII lowercase. | 757 // converted to ASCII lowercase. |
| 709 AtomicString local_name = ConvertLocalName(name); | 758 AtomicString local_name = ConvertLocalName(name); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 739 return g_empty_string; | 788 return g_empty_string; |
| 740 | 789 |
| 741 if (impl.hasIs()) | 790 if (impl.hasIs()) |
| 742 return impl.is(); | 791 return impl.is(); |
| 743 } | 792 } |
| 744 | 793 |
| 745 return g_empty_string; | 794 return g_empty_string; |
| 746 } | 795 } |
| 747 | 796 |
| 748 // https://dom.spec.whatwg.org/#dom-document-createelement | 797 // https://dom.spec.whatwg.org/#dom-document-createelement |
| 749 Element* Document::createElement(const AtomicString& local_name, | 798 Element* Document::createElement(const LocalDOMWindow* window, |
| 799 const AtomicString& local_name, |
| 750 const StringOrDictionary& string_or_options, | 800 const StringOrDictionary& string_or_options, |
| 751 ExceptionState& exception_state) { | 801 ExceptionState& exception_state) { |
| 752 // 1. If localName does not match Name production, throw InvalidCharacterError | 802 // 1. If localName does not match Name production, throw InvalidCharacterError |
| 753 if (!IsValidName(local_name)) { | 803 if (!IsValidElementName(window, local_name)) { |
| 754 exception_state.ThrowDOMException( | 804 exception_state.ThrowDOMException( |
| 755 kInvalidCharacterError, | 805 kInvalidCharacterError, |
| 756 "The tag name provided ('" + local_name + "') is not a valid name."); | 806 "The tag name provided ('" + local_name + "') is not a valid name."); |
| 757 return nullptr; | 807 return nullptr; |
| 758 } | 808 } |
| 759 | 809 |
| 760 // 2. localName converted to ASCII lowercase | 810 // 2. localName converted to ASCII lowercase |
| 761 const AtomicString& converted_local_name = ConvertLocalName(local_name); | 811 const AtomicString& converted_local_name = ConvertLocalName(local_name); |
| 762 | 812 |
| 763 bool is_v1 = string_or_options.isDictionary() || !RegistrationContext(); | 813 bool is_v1 = string_or_options.isDictionary() || !RegistrationContext(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 | 849 |
| 800 if (definition) { | 850 if (definition) { |
| 801 element = CustomElement::CreateCustomElementSync( | 851 element = CustomElement::CreateCustomElementSync( |
| 802 *this, converted_local_name, definition); | 852 *this, converted_local_name, definition); |
| 803 } else if (V0CustomElement::IsValidName(local_name) && | 853 } else if (V0CustomElement::IsValidName(local_name) && |
| 804 RegistrationContext()) { | 854 RegistrationContext()) { |
| 805 element = RegistrationContext()->CreateCustomTagElement( | 855 element = RegistrationContext()->CreateCustomTagElement( |
| 806 *this, | 856 *this, |
| 807 QualifiedName(g_null_atom, converted_local_name, xhtmlNamespaceURI)); | 857 QualifiedName(g_null_atom, converted_local_name, xhtmlNamespaceURI)); |
| 808 } else { | 858 } else { |
| 809 element = createElement(local_name, exception_state); | 859 element = createElement(window, local_name, exception_state); |
| 810 if (exception_state.HadException()) | 860 if (exception_state.HadException()) |
| 811 return nullptr; | 861 return nullptr; |
| 812 } | 862 } |
| 813 | 863 |
| 814 // 8. If 'is' is non-null, set 'is' attribute | 864 // 8. If 'is' is non-null, set 'is' attribute |
| 815 if (!is.IsEmpty()) { | 865 if (!is.IsEmpty()) { |
| 816 if (string_or_options.isString()) { | 866 if (string_or_options.isString()) { |
| 817 V0CustomElementRegistrationContext::SetIsAttributeAndTypeExtension( | 867 V0CustomElementRegistrationContext::SetIsAttributeAndTypeExtension( |
| 818 element, is); | 868 element, is); |
| 819 } else if (string_or_options.isDictionary()) { | 869 } else if (string_or_options.isDictionary()) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 839 kNamespaceError, | 889 kNamespaceError, |
| 840 "The namespace URI provided ('" + namespace_uri + | 890 "The namespace URI provided ('" + namespace_uri + |
| 841 "') is not valid for the qualified name provided ('" + | 891 "') is not valid for the qualified name provided ('" + |
| 842 qualified_name + "')."); | 892 qualified_name + "')."); |
| 843 return QualifiedName::Null(); | 893 return QualifiedName::Null(); |
| 844 } | 894 } |
| 845 | 895 |
| 846 return q_name; | 896 return q_name; |
| 847 } | 897 } |
| 848 | 898 |
| 849 Element* Document::createElementNS(const AtomicString& namespace_uri, | 899 Element* Document::createElementNS(const LocalDOMWindow* window, |
| 900 const AtomicString& namespace_uri, |
| 850 const AtomicString& qualified_name, | 901 const AtomicString& qualified_name, |
| 851 ExceptionState& exception_state) { | 902 ExceptionState& exception_state) { |
| 852 QualifiedName q_name( | 903 QualifiedName q_name( |
| 853 CreateQualifiedName(namespace_uri, qualified_name, exception_state)); | 904 CreateQualifiedName(namespace_uri, qualified_name, exception_state)); |
| 854 if (q_name == QualifiedName::Null()) | 905 if (q_name == QualifiedName::Null()) |
| 855 return nullptr; | 906 return nullptr; |
| 856 | 907 |
| 857 if (CustomElement::ShouldCreateCustomElement(q_name)) | 908 if (CustomElement::ShouldCreateCustomElement(q_name)) |
| 858 return CustomElement::CreateCustomElementSync(*this, q_name); | 909 return CustomElement::CreateCustomElementSync(*this, q_name); |
| 859 return createElement(q_name, kCreatedByCreateElement); | 910 return createElement(q_name, kCreatedByCreateElement); |
| 860 } | 911 } |
| 861 | 912 |
| 862 // https://dom.spec.whatwg.org/#internal-createelementns-steps | 913 // https://dom.spec.whatwg.org/#internal-createelementns-steps |
| 863 Element* Document::createElementNS(const AtomicString& namespace_uri, | 914 Element* Document::createElementNS(const LocalDOMWindow* window, |
| 915 const AtomicString& namespace_uri, |
| 864 const AtomicString& qualified_name, | 916 const AtomicString& qualified_name, |
| 865 const StringOrDictionary& string_or_options, | 917 const StringOrDictionary& string_or_options, |
| 866 ExceptionState& exception_state) { | 918 ExceptionState& exception_state) { |
| 867 // 1. Validate and extract | 919 // 1. Validate and extract |
| 868 QualifiedName q_name( | 920 QualifiedName q_name( |
| 869 CreateQualifiedName(namespace_uri, qualified_name, exception_state)); | 921 CreateQualifiedName(namespace_uri, qualified_name, exception_state)); |
| 870 if (q_name == QualifiedName::Null()) | 922 if (q_name == QualifiedName::Null()) |
| 871 return nullptr; | 923 return nullptr; |
| 872 | 924 |
| 873 bool is_v1 = string_or_options.isDictionary() || !RegistrationContext(); | 925 bool is_v1 = string_or_options.isDictionary() || !RegistrationContext(); |
| 874 bool create_v1_builtin = | 926 bool create_v1_builtin = |
| 875 string_or_options.isDictionary() && | 927 string_or_options.isDictionary() && |
| 876 RuntimeEnabledFeatures::customElementsBuiltinEnabled(); | 928 RuntimeEnabledFeatures::customElementsBuiltinEnabled(); |
| 877 bool should_create_builtin = | 929 bool should_create_builtin = |
| 878 create_v1_builtin || string_or_options.isString(); | 930 create_v1_builtin || string_or_options.isString(); |
| 879 | 931 |
| 880 // 2. | 932 // 2. |
| 881 const AtomicString& is = | 933 const AtomicString& is = |
| 882 AtomicString(GetTypeExtension(this, string_or_options, exception_state)); | 934 AtomicString(GetTypeExtension(this, string_or_options, exception_state)); |
| 883 const AtomicString& name = should_create_builtin ? is : qualified_name; | 935 const AtomicString& name = should_create_builtin ? is : qualified_name; |
| 884 | 936 |
| 885 if (!IsValidName(qualified_name)) { | 937 if (!IsValidElementName(window, qualified_name)) { |
| 886 exception_state.ThrowDOMException( | 938 exception_state.ThrowDOMException( |
| 887 kInvalidCharacterError, "The tag name provided ('" + qualified_name + | 939 kInvalidCharacterError, "The tag name provided ('" + qualified_name + |
| 888 "') is not a valid name."); | 940 "') is not a valid name."); |
| 889 return nullptr; | 941 return nullptr; |
| 890 } | 942 } |
| 891 | 943 |
| 892 // 3. Let definition be result of lookup up custom element definition | 944 // 3. Let definition be result of lookup up custom element definition |
| 893 CustomElementDefinition* definition = nullptr; | 945 CustomElementDefinition* definition = nullptr; |
| 894 if (is_v1) { | 946 if (is_v1) { |
| 895 const CustomElementDescriptor desc = | 947 const CustomElementDescriptor desc = |
| (...skipping 5795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6691 } | 6743 } |
| 6692 | 6744 |
| 6693 void showLiveDocumentInstances() { | 6745 void showLiveDocumentInstances() { |
| 6694 WeakDocumentSet& set = liveDocumentSet(); | 6746 WeakDocumentSet& set = liveDocumentSet(); |
| 6695 fprintf(stderr, "There are %u documents currently alive:\n", set.size()); | 6747 fprintf(stderr, "There are %u documents currently alive:\n", set.size()); |
| 6696 for (blink::Document* document : set) | 6748 for (blink::Document* document : set) |
| 6697 fprintf(stderr, "- Document %p URL: %s\n", document, | 6749 fprintf(stderr, "- Document %p URL: %s\n", document, |
| 6698 document->Url().GetString().Utf8().data()); | 6750 document->Url().GetString().Utf8().data()); |
| 6699 } | 6751 } |
| 6700 #endif | 6752 #endif |
| OLD | NEW |