Commit 8b8b60fb authored by Frédéric Wang's avatar Frédéric Wang Committed by Commit Bot

[mathml] Introduce base setup for MathMLElement under a MathMLCore flag

This prepares implementation of the MathML Core specification:
https://www.chromestatus.com/feature/5240822173794304

Minimal changes are applied to the build system in order to generate
element classes for MathML elements, similarly to how it is currently
done for HTML and SVG elements.

A folder third_party/blink/renderer/core/mathml is created with the json
files describing MathML attributes/elements as well as a simple
implementation of a new MathMLElement class. For now, no new MathML
attributes/elements are added and MathMLElement derives from Element
without performing any implementation change. MathMLElement also
contains standard helper functions in its header file.

A new experimental feature MathMLCore is also introduced. When it is
enabled, the document class will create MathMLElement instances for all
MathML elements. When it is disabled, it will continue to just create
Element instances.

No new tests are added since there is no visible behavior change,
independently of whether MathMLCore is enabled or not.

Bug: 6606
Change-Id: I59c2ad8f70383716c5514f2ab3c818bdc11cb8e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1895661Reviewed-by: default avatarMason Freed <masonfreed@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Frédéric Wang <fwang@igalia.com>
Cr-Commit-Position: refs/heads/master@{#713215}
parent 3774cf17
......@@ -16,6 +16,7 @@ SPECIAL_TOKENS = [
'Base64',
'IFrame',
'Latin1',
'MathML',
'PlugIn',
'SQLite',
'Uint16',
......
......@@ -188,6 +188,7 @@ component("core") {
"//third_party/blink/renderer/core/layout",
"//third_party/blink/renderer/core/layout/svg:svg_layout",
"//third_party/blink/renderer/core/loader",
"//third_party/blink/renderer/core/mathml",
"//third_party/blink/renderer/core/messaging",
"//third_party/blink/renderer/core/mojo",
"//third_party/blink/renderer/core/offscreencanvas",
......@@ -653,6 +654,33 @@ process_json5_files("make_core_generated_html_element_type_helpers") {
]
}
process_json5_files("make_core_generated_mathml_names") {
script = "../build/scripts/make_element_factory.py"
in_files = [
"mathml/mathml_tag_names.json5",
"mathml/mathml_attribute_names.json5",
]
other_inputs = make_element_factory_files
outputs = [
"$blink_core_output_dir/mathml_element_factory.cc",
"$blink_core_output_dir/mathml_element_factory.h",
"$blink_core_output_dir/mathml_names.cc",
"$blink_core_output_dir/mathml_names.h",
]
}
process_json5_files("make_core_generated_mathml_element_type_helpers") {
script = "../build/scripts/make_element_type_helpers.py"
in_files = [ "mathml/mathml_tag_names.json5" ]
other_inputs = make_element_type_helpers_files
outputs = [
"$blink_core_output_dir/mathml_element_type_helpers.cc",
"$blink_core_output_dir/mathml_element_type_helpers.h",
]
}
process_json5_files("make_core_generated_svg_names") {
script = "../build/scripts/make_element_factory.py"
......@@ -755,17 +783,6 @@ make_names("make_core_generated_enter_key_hint_names") {
# make_qualified_names ---------------------------------------------------------
make_qualified_names("make_core_generated_math_ml_names") {
in_files = [
"html/parser/mathml_tag_names.json5",
"html/parser/mathml_attribute_names.json5",
]
outputs = [
"$blink_core_output_dir/mathml_names.cc",
"$blink_core_output_dir/mathml_names.h",
]
}
make_qualified_names("make_core_generated_xlink_names") {
in_files = [ "svg/xlink_attribute_names.json5" ]
outputs = [
......@@ -1033,7 +1050,8 @@ targets_generating_sources = [
":make_core_generated_html_tokenizer_names",
":make_core_generated_input_mode_names",
":make_core_generated_input_type_names",
":make_core_generated_math_ml_names",
":make_core_generated_mathml_names",
":make_core_generated_mathml_element_type_helpers",
":make_core_generated_media_feature_names",
":make_core_generated_media_type_names",
":make_core_generated_performance_entry_names",
......
......@@ -244,6 +244,9 @@
#include "third_party/blink/renderer/core/loader/prerenderer_client.h"
#include "third_party/blink/renderer/core/loader/progress_tracker.h"
#include "third_party/blink/renderer/core/loader/text_resource_decoder_builder.h"
#include "third_party/blink/renderer/core/mathml/mathml_element.h"
#include "third_party/blink/renderer/core/mathml_element_factory.h"
#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
......@@ -1385,6 +1388,14 @@ Element* Document::CreateRawElement(const QualifiedName& qname,
if (!element)
element = MakeGarbageCollected<SVGUnknownElement>(qname, *this);
saw_elements_in_known_namespaces_ = true;
} else if (RuntimeEnabledFeatures::MathMLCoreEnabled() &&
qname.NamespaceURI() == mathml_names::kNamespaceURI) {
element = MathMLElementFactory::Create(qname.LocalName(), *this, flags);
// TODO(crbug.com/1021837): Determine if we need to introduce a
// MathMLUnknownClass.
if (!element)
element = MakeGarbageCollected<MathMLElement>(qname, *this);
saw_elements_in_known_namespaces_ = true;
} else {
element = Element::Create(qname, this);
}
......
......@@ -1701,8 +1701,8 @@ bool Node::CanStartSelection() const {
// inline style, or other things that this apparently guards against.
bool Node::IsStyledElement() const {
auto* this_element = DynamicTo<Element>(this);
return IsHTMLElement() || IsSVGElement() ||
(this_element &&
return IsHTMLElement() || IsSVGElement() || IsMathMLElement() ||
(!RuntimeEnabledFeatures::MathMLCoreEnabled() && this_element &&
this_element->namespaceURI() == mathml_names::kNamespaceURI);
}
......
......@@ -58,6 +58,7 @@ class KURL;
class LayoutBox;
class LayoutBoxModelObject;
class LayoutObject;
class MathMLQualifiedName;
class MutationObserver;
class MutationObserverRegistration;
class NodeList;
......@@ -79,8 +80,8 @@ class V8ScrollStateCallback;
class WebPluginContainerImpl;
struct PhysicalRect;
const int kNodeStyleChangeShift = 18;
const int kNodeCustomElementShift = 20;
const int kNodeStyleChangeShift = 19;
const int kNodeCustomElementShift = 21;
// Values for kChildNeedsStyleRecalcFlag, controlling whether a node gets its
// style recalculated.
......@@ -180,6 +181,7 @@ class CORE_EXPORT Node : public EventTarget {
// DOM methods & attributes for Node
bool HasTagName(const HTMLQualifiedName&) const;
bool HasTagName(const MathMLQualifiedName&) const;
bool HasTagName(const SVGQualifiedName&) const;
virtual String nodeName() const = 0;
virtual String nodeValue() const;
......@@ -272,6 +274,7 @@ class CORE_EXPORT Node : public EventTarget {
bool IsContainerNode() const { return GetFlag(kIsContainerFlag); }
bool IsTextNode() const { return GetFlag(kIsTextFlag); }
bool IsHTMLElement() const { return GetFlag(kIsHTMLFlag); }
bool IsMathMLElement() const { return GetFlag(kIsMathMLFlag); }
bool IsSVGElement() const { return GetFlag(kIsSVGFlag); }
DISABLE_CFI_PERF bool IsPseudoElement() const {
......@@ -915,56 +918,57 @@ class CORE_EXPORT Node : public EventTarget {
kIsContainerFlag = 1 << 2,
kIsElementFlag = 1 << 3,
kIsHTMLFlag = 1 << 4,
kIsSVGFlag = 1 << 5,
kIsDocumentFragmentFlag = 1 << 6,
kIsV0InsertionPointFlag = 1 << 7,
kIsMathMLFlag = 1 << 5,
kIsSVGFlag = 1 << 6,
kIsDocumentFragmentFlag = 1 << 7,
kIsV0InsertionPointFlag = 1 << 8,
// Changes based on if the element should be treated like a link,
// ex. When setting the href attribute on an <a>.
kIsLinkFlag = 1 << 8,
kIsLinkFlag = 1 << 9,
// Changes based on :hover, :active and :focus state.
kIsUserActionElementFlag = 1 << 9,
kIsUserActionElementFlag = 1 << 10,
// Tree state flags. These change when the element is added/removed
// from a DOM tree.
kIsConnectedFlag = 1 << 10,
kIsInShadowTreeFlag = 1 << 11,
kIsConnectedFlag = 1 << 11,
kIsInShadowTreeFlag = 1 << 12,
// Set by the parser when the children are done parsing.
kIsFinishedParsingChildrenFlag = 1 << 12,
kIsFinishedParsingChildrenFlag = 1 << 13,
// Flags related to recalcStyle.
kHasCustomStyleCallbacksFlag = 1 << 13,
kChildNeedsStyleInvalidationFlag = 1 << 14,
kNeedsStyleInvalidationFlag = 1 << 15,
kChildNeedsDistributionRecalcFlag = 1 << 16,
kChildNeedsStyleRecalcFlag = 1 << 17,
kHasCustomStyleCallbacksFlag = 1 << 14,
kChildNeedsStyleInvalidationFlag = 1 << 15,
kNeedsStyleInvalidationFlag = 1 << 16,
kChildNeedsDistributionRecalcFlag = 1 << 17,
kChildNeedsStyleRecalcFlag = 1 << 18,
kStyleChangeMask =
1 << kNodeStyleChangeShift | 1 << (kNodeStyleChangeShift + 1),
kCustomElementStateMask = 0x3 << kNodeCustomElementShift,
kHasNameOrIsEditingTextFlag = 1 << 22,
kHasEventTargetDataFlag = 1 << 23,
kHasNameOrIsEditingTextFlag = 1 << 23,
kHasEventTargetDataFlag = 1 << 24,
kV0CustomElementFlag = 1 << 24,
kV0CustomElementUpgradedFlag = 1 << 25,
kV0CustomElementFlag = 1 << 25,
kV0CustomElementUpgradedFlag = 1 << 26,
kNeedsReattachLayoutTree = 1 << 26,
kChildNeedsReattachLayoutTree = 1 << 27,
kNeedsReattachLayoutTree = 1 << 27,
kChildNeedsReattachLayoutTree = 1 << 28,
kHasDuplicateAttributes = 1 << 28,
kHasDuplicateAttributes = 1 << 29,
// Temporary flag for some UseCounter items. crbug.com/859391.
kInDOMNodeRemovedHandler = 1 << 29,
kInDOMNodeRemovedHandler = 1 << 30,
kForceReattachLayoutTree = 1 << 30,
kForceReattachLayoutTree = 1 << 31,
kDefaultNodeFlags = kIsFinishedParsingChildrenFlag,
};
// 1 bit remaining.
// 0 bits remaining.
bool GetFlag(NodeFlags mask) const { return node_flags_ & mask; }
void SetFlag(bool f, NodeFlags mask) {
......@@ -983,6 +987,7 @@ class CORE_EXPORT Node : public EventTarget {
kCreateContainer | kIsDocumentFragmentFlag | kIsInShadowTreeFlag,
kCreateDocumentFragment = kCreateContainer | kIsDocumentFragmentFlag,
kCreateHTMLElement = kCreateElement | kIsHTMLFlag,
kCreateMathMLElement = kCreateElement | kIsMathMLFlag,
kCreateSVGElement = kCreateElement | kIsSVGFlag,
kCreateDocument = kCreateContainer | kIsConnectedFlag,
kCreateV0InsertionPoint = kCreateHTMLElement | kIsV0InsertionPointFlag,
......
{
metadata: {
namespace: "MathML",
namespaceURI: "http://www.w3.org/1998/Math/MathML",
},
data: [
"math",
"mi",
"mn",
"mo",
"mtext",
"ms",
"mglyph",
"malignmark",
"annotation-xml",
],
}
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("mathml") {
sources = [
"mathml_element.cc",
"mathml_element.h",
]
}
......@@ -3,6 +3,7 @@
namespace: "MathML",
namespaceURI: "http://www.w3.org/1998/Math/MathML",
attrsNullNamespace: true,
export: "CORE_EXPORT",
},
data: [
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/mathml/mathml_element.h"
namespace blink {
MathMLElement::MathMLElement(const QualifiedName& tagName,
Document& document,
ConstructionType constructionType)
: Element(tagName, &document, constructionType) {}
MathMLElement::~MathMLElement() {}
} // namespace blink
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_ELEMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
class CORE_EXPORT MathMLElement : public Element {
public:
MathMLElement(const QualifiedName& tagName,
Document& document,
ConstructionType constructionType = kCreateMathMLElement);
~MathMLElement() override;
bool HasTagName(const MathMLQualifiedName& name) const {
return HasLocalName(name.LocalName());
}
private:
bool IsMathMLElement() const =
delete; // This will catch anyone doing an unnecessary check.
};
DEFINE_ELEMENT_TYPE_CASTS(MathMLElement, IsMathMLElement());
template <>
struct DowncastTraits<MathMLElement> {
static bool AllowFrom(const Node& node) { return node.IsMathMLElement(); }
};
template <typename T>
bool IsElementOfType(const MathMLElement&);
template <>
inline bool IsElementOfType<const MathMLElement>(const MathMLElement&) {
return true;
}
inline bool Node::HasTagName(const MathMLQualifiedName& name) const {
auto* mathml_element = DynamicTo<MathMLElement>(this);
return mathml_element && mathml_element->HasTagName(name);
}
// This requires IsMathML*Element(const MathMLElement&).
#define DEFINE_MATHMLELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType) \
inline bool Is##thisType(const thisType* element); \
inline bool Is##thisType(const thisType& element); \
inline bool Is##thisType(const MathMLElement* element) { \
return element && Is##thisType(*element); \
} \
inline bool Is##thisType(const Node& node) { \
auto* mathml_element = DynamicTo<MathMLElement>(node); \
return mathml_element && Is##thisType(mathml_element); \
} \
inline bool Is##thisType(const Node* node) { \
return node && Is##thisType(*node); \
} \
template <typename T> \
inline bool Is##thisType(const Member<T>& node) { \
return Is##thisType(node.Get()); \
} \
template <> \
inline bool IsElementOfType<const thisType>(const MathMLElement& element) { \
return Is##thisType(element); \
} \
DEFINE_ELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType)
} // namespace blink
#include "third_party/blink/renderer/core/mathml_element_type_helpers.h"
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_ELEMENT_H_
{
metadata: {
namespace: "MathML",
namespaceURI: "http://www.w3.org/1998/Math/MathML",
fallbackInterfaceName: "MathMLElement",
fallbackJSInterfaceName: "Element",
export: "CORE_EXPORT",
},
data: [
{
name: "math",
interfaceName: "MathMLElement",
},
{
name: "mi",
interfaceName: "MathMLElement",
},
{
name: "mn",
interfaceName: "MathMLElement",
},
{
name: "mo",
interfaceName: "MathMLElement",
},
{
name: "mtext",
interfaceName: "MathMLElement",
},
{
name: "ms",
interfaceName: "MathMLElement",
},
{
name: "mglyph",
interfaceName: "MathMLElement",
},
{
name: "malignmark",
interfaceName: "MathMLElement",
},
{
name: "annotation",
interfaceName: "MathMLElement",
},
{
name: "annotation-xml",
interfaceName: "MathMLElement",
},
{
name: "semantics",
interfaceName: "MathMLElement",
},
]
}
......@@ -925,6 +925,9 @@
name:"ManualSlotting",
status:"experimental",
},
{
name: "MathMLCore",
},
{
name:"MeasureMemory",
status:"experimental",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment