3 # Copyright (C) 2005-2007, 2009, 2013-2014 Apple Inc. All rights reserved.
4 # Copyright (C) 2009, Julien Chaffraix <jchaffraix@webkit.org>
5 # Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
6 # Copyright (C) 2011 Ericsson AB. All rights reserved.
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
12 # 1. Redistributions of source code must retain the above copyright
13 # notice, this list of conditions and the following disclaimer.
14 # 2. Redistributions in binary form must reproduce the above copyright
15 # notice, this list of conditions and the following disclaimer in the
16 # documentation and/or other materials provided with the distribution.
17 # 3. Neither the name of Apple Inc. ("Apple") nor the names of
18 # its contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
21 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
22 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
25 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 my $printWrapperFactory = 0;
54 my %enabledAttrs = ();
61 my %extensionAttrs = ();
67 $ccLocation = $ENV{CC};
68 } elsif (($Config::Config{"osname"}) =~ /solaris/i) {
69 $ccLocation = "/usr/sfw/bin/gcc";
70 } elsif ($Config::Config{"osname"} eq "darwin" && $ENV{SDKROOT}) {
71 chomp($ccLocation = `xcrun -find cc -sdk '$ENV{SDKROOT}'`);
73 $ccLocation = "/usr/bin/cc";
76 my $preprocessor = "";
77 if ($Config::Config{"osname"} eq "MSWin32") {
78 $preprocessor = "\"$ccLocation\" /EP";
80 $preprocessor = $ccLocation . " -E -x c++";
84 'tags=s' => \$tagsFile,
85 'attrs=s' => \$attrsFile,
86 'factory' => \$printFactory,
87 'outputDir=s' => \$outputDir,
88 'extraDefines=s' => \$extraDefines,
89 'preprocessor=s' => \$preprocessor,
90 'wrapperFactory' => \$printWrapperFactory,
91 'fonts=s' => \$fontNamesIn
96 if (length($fontNamesIn)) {
97 my $names = new IO::File;
98 my $familyNamesFileBase = "WebKitFontFamily";
100 open($names, $fontNamesIn) or die "Failed to open file: $fontNamesIn";
103 my $Parser = InFilesParser->new();
105 $Parser->parse($names, \¶metersHandler, \&dummy);
108 my $header = File::Spec->catfile($outputDir, "${familyNamesFileBase}Names.h");
109 open F, ">$header" or die "Unable to open $header for writing.";
111 printLicenseHeader($F);
112 printHeaderHead($F, "CSS", $familyNamesFileBase, "#include <wtf/text/AtomicString.h>", "");
114 printMacros($F, "extern const WTF::AtomicString", "", \%parameters);
115 print F "#endif\n\n";
120 my $source = File::Spec->catfile($outputDir, "${familyNamesFileBase}Names.cpp");
121 open F, ">$source" or die "Unable to open $source for writing.";
123 printLicenseHeader($F);
124 printCppHead($F, "CSS", $familyNamesFileBase, "WTF");
126 print F StaticString::GenerateStrings(\%parameters);
128 for my $name (sort keys %parameters) {
129 print F "DEFINE_GLOBAL(AtomicString, $name)\n";
135 print F StaticString::GenerateStringAsserts(\%parameters);
137 for my $name (sort keys %parameters) {
138 # FIXME: Would like to use static_cast here, but there are differences in const
139 # depending on whether SKIP_STATIC_CONSTRUCTORS_ON_GCC is used, so stick with a
140 # C-style cast for now.
141 print F " new (NotNull, (void*)&$name) AtomicString(reinterpret_cast<StringImpl*>(&${name}Data));\n";
149 die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile));
151 if (length($tagsFile)) {
152 %allTags = %{readTags($tagsFile, 0)};
153 %enabledTags = %{readTags($tagsFile, 1)};
154 namesToStrings(\%allTags, \%allStrings);
157 if (length($attrsFile)) {
158 %allAttrs = %{readAttrs($attrsFile, 0)};
159 %enabledAttrs = %{readAttrs($attrsFile, 1)};
160 namesToStrings(\%allAttrs, \%allStrings);
163 die "You must specify a namespace (e.g. SVG) for <namespace>Names.h" unless $parameters{namespace};
164 die "You must specify a namespaceURI (e.g. http://www.w3.org/2000/svg)" unless $parameters{namespaceURI};
166 $parameters{namespacePrefix} = $parameters{namespace} unless $parameters{namespacePrefix};
167 $parameters{fallbackJSInterfaceName} = $parameters{fallbackInterfaceName} unless $parameters{fallbackJSInterfaceName};
169 my $typeHelpersBasePath = "$outputDir/$parameters{namespace}ElementTypeHelpers";
170 my $namesBasePath = "$outputDir/$parameters{namespace}Names";
171 my $factoryBasePath = "$outputDir/$parameters{namespace}ElementFactory";
172 my $wrapperFactoryFileName = "$parameters{namespace}ElementWrapperFactory";
174 printNamesHeaderFile("$namesBasePath.h");
175 printNamesCppFile("$namesBasePath.cpp");
176 printTypeHelpersHeaderFile("$typeHelpersBasePath.h");
179 printFactoryCppFile("$factoryBasePath.cpp");
180 printFactoryHeaderFile("$factoryBasePath.h");
183 if ($printWrapperFactory) {
184 printWrapperFactoryCppFile($outputDir, $wrapperFactoryFileName);
185 printWrapperFactoryHeaderFile($outputDir, $wrapperFactoryFileName);
188 ### Hash initialization
190 sub defaultTagPropertyHash
193 'constructorNeedsCreatedByParser' => 0,
194 'constructorNeedsFormElement' => 0,
195 'noConstructor' => 0,
196 'interfaceName' => defaultInterfaceName($_[0]),
197 # By default, the JSInterfaceName is the same as the interfaceName.
198 'JSInterfaceName' => defaultInterfaceName($_[0]),
199 'mapToTagName' => '',
200 'wrapperOnlyIfMediaIsAvailable' => 0,
201 'settingsConditional' => 0,
203 'runtimeConditional' => 0,
204 'customTypeHelper' => 0,
208 sub defaultParametersHash
212 'namespacePrefix' => '',
213 'namespaceURI' => '',
214 'guardFactoryWith' => '',
215 'tagsNullNamespace' => 0,
216 'attrsNullNamespace' => 0,
217 'fallbackInterfaceName' => '',
218 'fallbackJSInterfaceName' => '',
222 sub defaultInterfaceName
224 die "No namespace found" if !$parameters{namespace};
225 return $parameters{namespace} . upperCaseName($_[0]) . "Element"
233 my $value = $extensionAttrs{$name};
245 my $namesRef = shift;
246 my $stringsRef = shift;
248 my %names = %$namesRef;
250 for my $name (keys %names) {
251 $stringsRef->{$name} = valueForName($name);
257 my ($tag, $property, $value) = @_;
261 # Initialize default property values.
262 $parsedTags{$tag} = { defaultTagPropertyHash($tag) } if !defined($parsedTags{$tag});
265 die "Unknown property $property for tag $tag\n" if !defined($parsedTags{$tag}{$property});
267 # The code relies on JSInterfaceName deriving from interfaceName to check for custom JSInterfaceName.
268 # So override JSInterfaceName if it was not already set.
269 $parsedTags{$tag}{JSInterfaceName} = $value if $property eq "interfaceName" && $parsedTags{$tag}{JSInterfaceName} eq $parsedTags{$tag}{interfaceName};
271 $parsedTags{$tag}{$property} = $value;
277 my ($attr, $property, $value) = @_;
278 # Translate HTML5 extension attributes of the form 'x-webkit-feature' to 'webkitfeature'.
279 # We don't just check for the 'x-' prefix because there are attributes such as x-height
280 # which should follow the default path below.
281 if ($attr =~ m/^x-webkit-(.*)/) {
282 my $newAttr = "webkit$1";
283 $extensionAttrs{$newAttr} = $attr;
288 # Initialize default properties' values.
289 $parsedAttrs{$attr} = {} if !defined($parsedAttrs{$attr});
292 die "Unknown property $property for attribute $attr\n" if !defined($parsedAttrs{$attr}{$property});
293 $parsedAttrs{$attr}{$property} = $value;
297 sub parametersHandler
299 my ($parameter, $value) = @_;
301 # Initialize default properties' values.
302 %parameters = defaultParametersHash() if (!(keys %parameters) && $initDefaults);
304 die "Unknown parameter $parameter for tags/attrs\n" if (!defined($parameters{$parameter}) && $initDefaults);
305 $parameters{$parameter} = $value;
310 sub preprocessorCommand()
312 return $preprocessor if $extraDefines eq 0;
313 return $preprocessor . " -D" . join(" -D", split(" ", $extraDefines));
318 my ($namesFile, $hashToFillRef, $handler, $usePreprocessor) = @_;
320 my $names = new IO::File;
321 if ($usePreprocessor) {
322 open($names, preprocessorCommand() . " " . $namesFile . "|") or die "Failed to open file: $namesFile";
324 open($names, $namesFile) or die "Failed to open file: $namesFile";
327 my $InParser = InFilesParser->new();
328 $InParser->parse($names, \¶metersHandler, $handler);
331 die "Failed to read names from file: $namesFile" if (keys %{$hashToFillRef} == 0);
332 return $hashToFillRef;
337 my ($namesFile, $usePreprocessor) = @_;
339 return readNames($namesFile, \%parsedAttrs, \&attrsHandler, $usePreprocessor);
344 my ($namesFile, $usePreprocessor) = @_;
346 return readNames($namesFile, \%parsedTags, \&tagsHandler, $usePreprocessor);
351 my ($F, $macro, $suffix, $namesRef) = @_;
352 my %names = %$namesRef;
354 for my $name (sort keys %names) {
355 print F "$macro $name","$suffix;\n";
359 sub usesDefaultWrapper
362 return $tagName eq $parameters{namespace} . "Element";
365 # Build a direct mapping from the tags to the Element to create.
366 sub buildConstructorMap
368 my %tagConstructorMap = ();
369 for my $tagName (keys %enabledTags) {
370 my $interfaceName = $enabledTags{$tagName}{interfaceName};
372 if ($enabledTags{$tagName}{mapToTagName}) {
373 die "Cannot handle multiple mapToTagName for $tagName\n" if $enabledTags{$enabledTags{$tagName}{mapToTagName}}{mapToTagName};
374 $interfaceName = $enabledTags{ $enabledTags{$tagName}{mapToTagName} }{interfaceName};
377 # Chop the string to keep the interesting part.
378 $interfaceName =~ s/$parameters{namespace}(.*)Element/$1/;
379 $tagConstructorMap{$tagName} = lc($interfaceName);
382 return %tagConstructorMap;
385 # Helper method that print the constructor's signature avoiding
386 # unneeded arguments.
387 sub printConstructorSignature
389 my ($F, $tagName, $constructorName, $constructorTagName) = @_;
391 print F "static Ref<$parameters{namespace}Element> ${constructorName}Constructor(const QualifiedName& $constructorTagName, Document& document";
392 if ($parameters{namespace} eq "HTML") {
393 print F ", HTMLFormElement*";
394 print F " formElement" if $enabledTags{$tagName}{constructorNeedsFormElement};
397 print F " createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser};
401 # Helper method to dump the constructor interior and call the
402 # Element constructor with the right arguments.
403 # The variable names should be kept in sync with the previous method.
404 sub printConstructorInterior
406 my ($F, $tagName, $interfaceName, $constructorTagName) = @_;
408 # Handle media elements.
409 # Note that wrapperOnlyIfMediaIsAvailable is a misnomer, because media availability
410 # does not just control the wrapper; it controls the element object that is created.
411 # FIXME: Could we instead do this entirely in the wrapper, and use custom wrappers
412 # instead of having all the support for this here in this script?
413 if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
415 Settings* settings = document.settings();
416 if (!MediaPlayer::isAvailable() || (settings && !settings->mediaEnabled()))
417 return $parameters{fallbackInterfaceName}::create($constructorTagName, document);
423 my $runtimeConditional = $enabledTags{$tagName}{runtimeConditional};
424 if ($runtimeConditional) {
426 if (!RuntimeEnabledFeatures::sharedFeatures().${runtimeConditional}Enabled())
432 my $settingsConditional = $enabledTags{$tagName}{settingsConditional};
433 if ($settingsConditional) {
435 Settings* settings = document.settings();
436 if (!settings || !settings->${settingsConditional}())
437 return $parameters{fallbackInterfaceName}::create($constructorTagName, document);
442 # Call the constructor with the right parameters.
443 print F " return ${interfaceName}::create($constructorTagName, document";
444 print F ", formElement" if $enabledTags{$tagName}{constructorNeedsFormElement};
445 print F ", createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser};
449 sub printConstructors
451 my ($F, $tagConstructorMapRef) = @_;
452 my %tagConstructorMap = %$tagConstructorMapRef;
454 # This is to avoid generating the same constructor several times.
456 for my $tagName (sort keys %tagConstructorMap) {
457 my $interfaceName = $enabledTags{$tagName}{interfaceName};
459 # Ignore the mapped tag
460 # FIXME: It could be moved inside this loop but was split for readibility.
461 next if (defined($uniqueTags{$interfaceName}) || $enabledTags{$tagName}{mapToTagName});
462 # Tags can have wrappers without constructors.
463 # This is useful to make user-agent shadow elements internally testable
464 # while keeping them from being avaialble in the HTML markup.
465 next if $enabledTags{$tagName}{noConstructor};
467 $uniqueTags{$interfaceName} = '1';
469 my $conditional = $enabledTags{$tagName}{conditional};
471 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
472 print F "#if ${conditionalString}\n";
475 printConstructorSignature($F, $tagName, $tagConstructorMap{$tagName}, "tagName");
476 printConstructorInterior($F, $tagName, $interfaceName, "tagName");
485 # Mapped tag name uses a special wrapper to keep their prefix and namespaceURI while using the mapped localname.
486 for my $tagName (sort keys %tagConstructorMap) {
487 if ($enabledTags{$tagName}{mapToTagName}) {
488 my $mappedName = $enabledTags{$tagName}{mapToTagName};
489 printConstructorSignature($F, $mappedName, $mappedName . "To" . $tagName, "tagName");
490 printConstructorInterior($F, $mappedName, $enabledTags{$mappedName}{interfaceName}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())");
495 sub printFunctionTable
497 my ($F, $tagConstructorMap) = @_;
498 my %tagConstructorMap = %$tagConstructorMap;
500 for my $tagName (sort keys %tagConstructorMap) {
501 next if $enabledTags{$tagName}{noConstructor};
503 my $conditional = $enabledTags{$tagName}{conditional};
505 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
506 print F "#if ${conditionalString}\n";
509 if ($enabledTags{$tagName}{mapToTagName}) {
510 print F " { ${tagName}Tag, $enabledTags{$tagName}{mapToTagName}To${tagName}Constructor },\n";
512 print F " { ${tagName}Tag, $tagConstructorMap{$tagName}Constructor },\n";
521 sub svgCapitalizationHacks
525 $name = "FE" . ucfirst $1 if $name =~ /^fe(.+)$/;
534 $name = svgCapitalizationHacks($name) if ($parameters{namespace} eq "SVG");
536 while ($name =~ /^(.*?)_(.*)/) {
537 $name = $1 . ucfirst $2;
540 return ucfirst $name;
545 my ($F, $prefix, $namespace, $includes, $definitions) = @_;
548 #ifndef ${prefix}_${namespace}Names_h
550 #define ${prefix}_${namespace}Names_h
556 ${definitions}namespace ${namespace}Names {
558 #ifndef ${prefix}_${namespace}_NAMES_HIDE_GLOBALS
566 my ($F, $prefix, $namespace, $usedNamespace) = @_;
568 print F "#include \"config.h\"\n\n";
569 print F "#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n";
570 print F "#define ${prefix}_${namespace}_NAMES_HIDE_GLOBALS 1\n";
572 print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n";
573 print F "#endif\n\n";
575 print F "#include \"${namespace}Names.h\"\n\n";
576 print F "#include <wtf/StaticConstructors.h>\n";
578 print F "namespace WebCore {\n\n";
579 print F "namespace ${namespace}Names {\n\n";
580 print F "using namespace $usedNamespace;\n\n";
585 my ($F, $isDefinition) = @_;
588 print F "\nWEBCORE_EXPORT void init();\n\n";
590 print F "#endif\n\n";
594 print F "\nvoid init()
596 static bool initialized = false;
601 // Use placement new to initialize the globals.
603 AtomicString::init();
607 sub printLicenseHeader
611 * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
613 * This file was generated by the dom/make_names.pl script.
615 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
617 * Redistribution and use in source and binary forms, with or without
618 * modification, are permitted provided that the following conditions
620 * 1. Redistributions of source code must retain the above copyright
621 * notice, this list of conditions and the following disclaimer.
622 * 2. Redistributions in binary form must reproduce the above copyright
623 * notice, this list of conditions and the following disclaimer in the
624 * documentation and/or other materials provided with the distribution.
626 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
627 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
628 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
629 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
630 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
631 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
632 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
633 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
634 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
635 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
636 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
644 my ($F, $namesRef) = @_;
645 my %names = %$namesRef;
647 # Do a first pass to discard classes that map to several tags.
648 my %classToTags = ();
649 for my $name (keys %names) {
650 my $class = $parsedTags{$name}{interfaceName};
651 push(@{$classToTags{$class}}, $name) if defined $class;
654 for my $class (sort keys %classToTags) {
655 my $name = $classToTags{$class}[0];
656 next if $parsedTags{$name}{customTypeHelper};
657 # Skip classes that map to more than 1 tag.
658 my $tagCount = scalar @{$classToTags{$class}};
659 next if $tagCount > 1;
666 template <typename ArgType>
667 class TypeCastTraits<const WebCore::$class, ArgType, false /* isBaseType */> {
669 static bool isOfType(ArgType& node) { return checkTagName(node); }
673 if ($parameters{namespace} eq "HTML" && ($parsedTags{$name}{wrapperOnlyIfMediaIsAvailable} || $parsedTags{$name}{settingsConditional})) {
675 static bool checkTagName(const WebCore::HTMLElement& element) { return !element.isHTMLUnknownElement() && element.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
676 static bool checkTagName(const WebCore::Node& node) { return is<WebCore::HTMLElement>(node) && checkTagName(downcast<WebCore::HTMLElement>(node)); }
681 static bool checkTagName(const WebCore::$parameters{namespace}Element& element) { return element.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
682 static bool checkTagName(const WebCore::Node& node) { return node.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
695 sub printTypeHelpersHeaderFile
697 my ($headerPath) = shift;
699 open F, ">$headerPath";
700 printLicenseHeader($F);
702 print F "#ifndef ".$parameters{namespace}."ElementTypeHelpers_h\n";
703 print F "#define ".$parameters{namespace}."ElementTypeHelpers_h\n\n";
704 print F "#include \"".$parameters{namespace}."Names.h\"\n\n";
706 printTypeHelpers($F, \%allTags);
713 sub printNamesHeaderFile
715 my ($headerPath) = shift;
717 open F, ">$headerPath";
719 printLicenseHeader($F);
720 printHeaderHead($F, "DOM", $parameters{namespace}, '#include "QualifiedName.h"', "class $parameters{namespace}QualifiedName : public QualifiedName { };\n\n");
722 my $lowercaseNamespacePrefix = lc($parameters{namespacePrefix});
724 print F "// Namespace\n";
725 print F "WEBCORE_EXPORT extern const WTF::AtomicString ${lowercaseNamespacePrefix}NamespaceURI;\n\n";
729 printMacros($F, "WEBCORE_EXPORT extern const WebCore::$parameters{namespace}QualifiedName", "Tag", \%allTags);
732 if (keys %allAttrs) {
733 print F "// Attributes\n";
734 printMacros($F, "WEBCORE_EXPORT extern const WebCore::QualifiedName", "Attr", \%allAttrs);
736 print F "#endif\n\n";
739 print F "const unsigned $parameters{namespace}TagsCount = ", scalar(keys %allTags), ";\n";
740 print F "const WebCore::$parameters{namespace}QualifiedName* const* get$parameters{namespace}Tags();\n";
743 if (keys %allAttrs) {
744 print F "const unsigned $parameters{namespace}AttrsCount = ", scalar(keys %allAttrs), ";\n";
745 print F "const WebCore::QualifiedName* const* get$parameters{namespace}Attrs();\n";
752 sub printNamesCppFile
758 printLicenseHeader($F);
759 printCppHead($F, "DOM", $parameters{namespace}, "WebCore");
761 my $lowercaseNamespacePrefix = lc($parameters{namespacePrefix});
763 print F "WEBCORE_EXPORT DEFINE_GLOBAL(AtomicString, ${lowercaseNamespacePrefix}NamespaceURI)\n\n";
765 print F StaticString::GenerateStrings(\%allStrings);
769 for my $name (sort keys %allTags) {
770 print F "WEBCORE_EXPORT DEFINE_GLOBAL($parameters{namespace}QualifiedName, ", $name, "Tag)\n";
773 print F "\n\nconst WebCore::$parameters{namespace}QualifiedName* const* get$parameters{namespace}Tags()\n";
774 print F "{\n static const WebCore::$parameters{namespace}QualifiedName* const $parameters{namespace}Tags[] = {\n";
775 for my $name (sort keys %allTags) {
776 print F " reinterpret_cast<const WebCore::$parameters{namespace}QualifiedName*>(&${name}Tag),\n";
779 print F " return $parameters{namespace}Tags;\n";
783 if (keys %allAttrs) {
784 print F "\n// Attributes\n";
785 for my $name (sort keys %allAttrs) {
786 print F "WEBCORE_EXPORT DEFINE_GLOBAL(QualifiedName, ", $name, "Attr)\n";
788 print F "\n\nconst WebCore::QualifiedName* const* get$parameters{namespace}Attrs()\n";
789 print F "{\n static const WebCore::QualifiedName* const $parameters{namespace}Attrs[] = {\n";
790 for my $name (sort keys %allAttrs) {
791 print F " reinterpret_cast<const WebCore::QualifiedName*>(&${name}Attr),\n";
794 print F " return $parameters{namespace}Attrs;\n";
800 print(F " AtomicString ${lowercaseNamespacePrefix}NS(\"$parameters{namespaceURI}\", AtomicString::ConstructFromLiteral);\n\n");
802 print(F " // Namespace\n");
803 print(F " new (NotNull, (void*)&${lowercaseNamespacePrefix}NamespaceURI) AtomicString(${lowercaseNamespacePrefix}NS);\n");
805 print F StaticString::GenerateStringAsserts(\%allStrings);
808 my $tagsNamespace = $parameters{tagsNullNamespace} ? "nullAtom" : "${lowercaseNamespacePrefix}NS";
809 printDefinitions($F, \%allTags, "tags", $tagsNamespace);
811 if (keys %allAttrs) {
812 my $attrsNamespace = $parameters{attrsNullNamespace} ? "nullAtom" : "${lowercaseNamespacePrefix}NS";
813 printDefinitions($F, \%allAttrs, "attributes", $attrsNamespace);
816 print F "}\n\n} }\n\n";
820 sub printJSElementIncludes
825 for my $tagName (sort keys %enabledTags) {
826 my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
827 next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName);
828 if ($enabledTags{$tagName}{conditional}) {
829 # We skip feature-define-specific #includes here since we handle them separately.
832 $tagsSeen{$JSInterfaceName} = 1;
834 print F "#include \"JS${JSInterfaceName}.h\"\n";
836 print F "#include \"JS$parameters{fallbackJSInterfaceName}.h\"\n";
839 sub printElementIncludes
844 for my $tagName (sort keys %enabledTags) {
845 my $interfaceName = $enabledTags{$tagName}{interfaceName};
846 next if defined($tagsSeen{$interfaceName});
847 if ($enabledTags{$tagName}{conditional}) {
848 # We skip feature-define-specific #includes here since we handle them separately.
851 $tagsSeen{$interfaceName} = 1;
853 print F "#include \"${interfaceName}.h\"\n";
855 print F "#include \"$parameters{fallbackInterfaceName}.h\"\n";
858 sub printConditionalElementIncludes
860 my ($F, $wrapperIncludes) = @_;
863 my %unconditionalElementIncludes;
864 my %unconditionalJSElementIncludes;
866 for my $tagName (keys %enabledTags) {
867 my $conditional = $enabledTags{$tagName}{conditional};
868 my $interfaceName = $enabledTags{$tagName}{interfaceName};
869 my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
872 $conditionals{$conditional}{interfaceNames}{$interfaceName} = 1;
873 $conditionals{$conditional}{JSInterfaceNames}{$JSInterfaceName} = 1;
875 $unconditionalElementIncludes{$interfaceName} = 1;
876 $unconditionalJSElementIncludes{$JSInterfaceName} = 1;
880 for my $conditional (sort keys %conditionals) {
881 print F "\n#if ENABLE($conditional)\n";
882 for my $interfaceName (sort keys %{$conditionals{$conditional}{interfaceNames}}) {
883 next if $unconditionalElementIncludes{$interfaceName};
884 print F "#include \"$interfaceName.h\"\n";
886 if ($wrapperIncludes) {
887 for my $JSInterfaceName (sort keys %{$conditionals{$conditional}{JSInterfaceNames}}) {
888 next if $unconditionalJSElementIncludes{$JSInterfaceName};
889 print F "#include \"JS$JSInterfaceName.h\"\n";
898 my ($F, $namesRef, $type, $namespaceURI) = @_;
900 my $shortCamelType = ucfirst(substr(substr($type, 0, -1), 0, 4));
901 my $capitalizedType = ucfirst($type);
905 struct ${capitalizedType}TableEntry {
910 static const ${capitalizedType}TableEntry ${type}Table[] = {
913 for my $name (sort keys %$namesRef) {
914 print F " { (void*)&$name$shortCamelType, *reinterpret_cast<StringImpl*>(&${name}Data) },\n";
920 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(${type}Table); ++i)
923 if ($namespaceURI eq "nullAtom") {
924 print F " createQualifiedName(${type}Table[i].targetAddress, &${type}Table[i].name);\n";
926 print F " createQualifiedName(${type}Table[i].targetAddress, &${type}Table[i].name, $namespaceURI);\n";
930 ## ElementFactory routines
932 sub printFactoryCppFile
938 my $formElementArgumentForDeclaration = "";
939 my $formElementArgumentForDefinition = "";
940 $formElementArgumentForDeclaration = ", HTMLFormElement*" if $parameters{namespace} eq "HTML";
941 $formElementArgumentForDefinition = ", HTMLFormElement* formElement" if $parameters{namespace} eq "HTML";
943 printLicenseHeader($F);
950 print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
953 #include "$parameters{namespace}ElementFactory.h"
955 #include "$parameters{namespace}Names.h"
960 printElementIncludes($F);
961 printConditionalElementIncludes($F, 0);
965 #include "Document.h"
966 #include "RuntimeEnabledFeatures.h"
967 #include "Settings.h"
968 #include <wtf/HashMap.h>
969 #include <wtf/NeverDestroyed.h>
973 using namespace $parameters{namespace}Names;
975 typedef Ref<$parameters{namespace}Element> (*$parameters{namespace}ConstructorFunction)(const QualifiedName&, Document&$formElementArgumentForDeclaration, bool createdByParser);
980 my %tagConstructorMap = buildConstructorMap();
982 printConstructors($F, \%tagConstructorMap);
985 static NEVER_INLINE void populate$parameters{namespace}FactoryMap(HashMap<AtomicStringImpl*, $parameters{namespace}ConstructorFunction>& map)
988 const QualifiedName& name;
989 $parameters{namespace}ConstructorFunction function;
992 static const TableEntry table[] = {
996 printFunctionTable($F, \%tagConstructorMap);
1001 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(table); ++i)
1002 map.add(table[i].name.localName().impl(), table[i].function);
1005 Ref<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createElement(const QualifiedName& name, Document& document$formElementArgumentForDefinition, bool createdByParser)
1007 static NeverDestroyed<HashMap<AtomicStringImpl*, $parameters{namespace}ConstructorFunction>> functions;
1008 if (functions.get().isEmpty())
1009 populate$parameters{namespace}FactoryMap(functions);
1010 if ($parameters{namespace}ConstructorFunction function = functions.get().get(name.localName().impl()))
1014 if ($parameters{namespace} eq "HTML") {
1015 print F " return function(name, document, formElement, createdByParser);\n";
1017 print F " return function(name, document, createdByParser);\n";
1021 return $parameters{fallbackInterfaceName}::create(name, document);
1024 } // namespace WebCore
1029 print F "#endif\n" if $parameters{guardFactoryWith};
1034 sub printFactoryHeaderFile
1036 my $headerPath = shift;
1038 open F, ">$headerPath";
1040 printLicenseHeader($F);
1043 #ifndef $parameters{namespace}ElementFactory_h
1044 #define $parameters{namespace}ElementFactory_h
1046 #include <wtf/Forward.h>
1051 class HTMLFormElement;
1052 class QualifiedName;
1054 class $parameters{namespace}Element;
1056 class $parameters{namespace}ElementFactory {
1061 print F " static Ref<$parameters{namespace}Element> createElement(const QualifiedName&, Document&";
1062 print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
1063 print F ", bool createdByParser = false);\n";
1069 #endif // $parameters{namespace}ElementFactory_h
1077 ## Wrapper Factory routines
1079 sub usesDefaultJSWrapper
1083 # A tag reuses the default wrapper if its JSInterfaceName matches the default namespace Element.
1084 return $enabledTags{$name}{JSInterfaceName} eq $parameters{namespace} . "Element";
1087 sub printWrapperFunctions
1092 for my $tagName (sort keys %enabledTags) {
1093 # Avoid defining the same wrapper method twice.
1094 my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
1095 next if (defined($tagsSeen{$JSInterfaceName}) || (usesDefaultJSWrapper($tagName) && ($parameters{fallbackJSInterfaceName} eq $parameters{namespace} . "Element"))) && !$enabledTags{$tagName}{settingsConditional};
1096 $tagsSeen{$JSInterfaceName} = 1;
1098 my $conditional = $enabledTags{$tagName}{conditional};
1100 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
1101 print F "#if ${conditionalString}\n\n";
1104 if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
1106 static JSDOMWrapper* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1108 if (element->is$parameters{fallbackInterfaceName}())
1109 return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackInterfaceName}, element.get());
1110 return CREATE_DOM_WRAPPER(globalObject, ${JSInterfaceName}, element.get());
1115 } elsif ($enabledTags{$tagName}{settingsConditional}) {
1117 static JSDOMWrapper* create$enabledTags{$tagName}{interfaceName}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1119 if (element->is$parameters{fallbackInterfaceName}())
1120 return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackInterfaceName}, element.get());
1121 return CREATE_DOM_WRAPPER(globalObject, ${JSInterfaceName}, element.get());
1126 } elsif ($enabledTags{$tagName}{runtimeConditional}) {
1127 my $runtimeConditional = $enabledTags{$tagName}{runtimeConditional};
1129 static JSDOMWrapper* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1131 if (!RuntimeEnabledFeatures::sharedFeatures().${runtimeConditional}Enabled()) {
1132 ASSERT(!element || element->is$parameters{fallbackInterfaceName}());
1133 return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackJSInterfaceName}, element.get());
1136 return CREATE_DOM_WRAPPER(globalObject, ${JSInterfaceName}, element.get());
1142 static JSDOMWrapper* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1144 return CREATE_DOM_WRAPPER(globalObject, ${JSInterfaceName}, element.get());
1152 print F "#endif\n\n";
1157 sub printWrapperFactoryCppFile
1159 my $outputDir = shift;
1160 my $wrapperFactoryFileName = shift;
1162 open F, ">" . $outputDir . "/JS" . $wrapperFactoryFileName . ".cpp";
1164 printLicenseHeader($F);
1166 print F "#include \"config.h\"\n";
1167 print F "#include \"JS$parameters{namespace}ElementWrapperFactory.h\"\n\n";
1169 print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
1171 printJSElementIncludes($F);
1172 printElementIncludes($F);
1174 print F "\n#include \"$parameters{namespace}Names.h\"\n";
1177 #include "Document.h"
1178 #include "RuntimeEnabledFeatures.h"
1179 #include "Settings.h"
1180 #include <wtf/NeverDestroyed.h>
1181 #include <wtf/StdLibExtras.h>
1185 printConditionalElementIncludes($F, 1);
1189 using namespace JSC;
1193 using namespace $parameters{namespace}Names;
1195 typedef JSDOMWrapper* (*Create$parameters{namespace}ElementWrapperFunction)(JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>);
1200 printWrapperFunctions($F);
1204 static NEVER_INLINE void populate$parameters{namespace}WrapperMap(HashMap<AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction>& map)
1207 const QualifiedName& name;
1208 Create$parameters{namespace}ElementWrapperFunction function;
1211 static const TableEntry table[] = {
1215 for my $tag (sort keys %enabledTags) {
1216 # Do not add the name to the map if it does not have a JS wrapper constructor or uses the default wrapper.
1217 next if (usesDefaultJSWrapper($tag, \%enabledTags) && ($parameters{fallbackJSInterfaceName} eq $parameters{namespace} . "Element"));
1219 my $conditional = $enabledTags{$tag}{conditional};
1221 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
1222 print F "#if ${conditionalString}\n";
1226 if ($enabledTags{$tag}{settingsConditional}) {
1227 $ucTag = $enabledTags{$tag}{interfaceName};
1229 $ucTag = $enabledTags{$tag}{JSInterfaceName};
1232 # FIXME Remove unnecessary '&' from the following (print) line once we switch to a non-broken Visual Studio compiler.
1233 # https://bugs.webkit.org/show_bug.cgi?id=121235:
1234 print F " { ${tag}Tag, &create${ucTag}Wrapper },\n";
1244 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(table); ++i)
1245 map.add(table[i].name.localName().impl(), table[i].function);
1248 JSDOMWrapper* createJS$parameters{namespace}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1250 static NeverDestroyed<HashMap<AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction>> functions;
1251 if (functions.get().isEmpty())
1252 populate$parameters{namespace}WrapperMap(functions);
1253 if (auto function = functions.get().get(element->localName().impl()))
1254 return function(globalObject, element);
1255 return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackJSInterfaceName}, element.get());
1262 print F "\n#endif\n" if $parameters{guardFactoryWith};
1267 sub printWrapperFactoryHeaderFile
1269 my $outputDir = shift;
1270 my $wrapperFactoryFileName = shift;
1272 open F, ">" . $outputDir . "/JS" . $wrapperFactoryFileName . ".h";
1274 printLicenseHeader($F);
1276 print F "#ifndef JS$parameters{namespace}ElementWrapperFactory_h\n";
1277 print F "#define JS$parameters{namespace}ElementWrapperFactory_h\n\n";
1279 print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith};
1282 #include <wtf/Forward.h>
1287 class JSDOMGlobalObject;
1288 class $parameters{namespace}Element;
1290 JSDOMWrapper* createJS$parameters{namespace}Wrapper(JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>);
1297 print F "#endif // $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
1299 print F "#endif // JS$parameters{namespace}ElementWrapperFactory_h\n";