chromium/third_party/blink/renderer/build/scripts/templates/element_factory.cc.tmpl

{% from "templates/macros.tmpl" import license, source_files_for_generated_file %}
{{ license() }}

{{source_files_for_generated_file(template_file, input_files)}}

#include "third_party/blink/renderer/core/{{namespace|lower}}_element_factory.h"

#include <iterator>

#include "third_party/blink/renderer/core/{{namespace|lower}}_names.h"
{% for header in tags|groupby('interface_header') %}
#include "{{header[0]}}"
{% endfor %}
{% if fallback_interface %}
#include "third_party/blink/renderer/core/{{namespace|lower}}/{{fallback_interface_header}}"
{% endif %}
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"

namespace blink {

using {{namespace}}ConstructorFunction = {{namespace}}Element* (*)(
    Document&, const CreateElementFlags);

using {{namespace}}FunctionMap = HashMap<AtomicString, {{namespace}}ConstructorFunction>;

static {{namespace}}FunctionMap* g_{{namespace|lower}}_constructors = nullptr;

{% for tag in tags|sort(attribute='name') if not tag.noConstructor %}
static {{namespace}}Element* {{namespace}}{{tag.name.to_upper_camel_case()}}Constructor(
    Document& document, const CreateElementFlags flags) {
  {% if tag.runtimeEnabled %}
  if (!RuntimeEnabledFeatures::{{tag.runtimeEnabled}}Enabled(document.GetExecutionContext()))
    return MakeGarbageCollected<{{fallback_interface}}>({{cpp_namespace}}::{{tag|symbol}}Tag, document);
  {% endif %}
  return MakeGarbageCollected<{{tag.interface}}>(
      {%- if tag.multipleTagNames %}{{cpp_namespace}}::{{tag|symbol}}Tag, {% endif -%}
      document
      {%- if tag.constructorNeedsCreateElementFlags %}, flags{% endif -%}
  );
}
{% endfor %}

struct Create{{namespace}}FunctionMapData {
  const QualifiedName& tag;
  {{namespace}}ConstructorFunction func;
};

static void Create{{namespace}}FunctionMap() {
  DCHECK(!g_{{namespace|lower}}_constructors);
  g_{{namespace|lower}}_constructors = new {{namespace}}FunctionMap;
  // Empty array initializer lists are illegal [dcl.init.aggr] and will not
  // compile in MSVC. If tags list is empty, add check to skip this.
  static const Create{{namespace}}FunctionMapData data[] = {
  {% for tag in tags|sort(attribute='name') if not tag.noConstructor %}
    { {{cpp_namespace}}::{{tag|symbol}}Tag, {{namespace}}{{tag.name.to_upper_camel_case()}}Constructor },
  {% endfor %}
  };
  for (size_t i = 0; i < std::size(data); i++)
    g_{{namespace|lower}}_constructors->Set(data[i].tag.LocalName(), data[i].func);
}

{{namespace}}Element* {{namespace}}ElementFactory::Create(
    const AtomicString& local_name,
    Document& document,
    const CreateElementFlags flags) {
  if (!g_{{namespace|lower}}_constructors)
    Create{{namespace}}FunctionMap();
  auto it = g_{{namespace|lower}}_constructors->find(local_name);
  if (it == g_{{namespace|lower}}_constructors->end())
    return nullptr;
  {{namespace}}ConstructorFunction function = it->value;
  return function(document, flags);
}

}  // namespace blink