0c7871892a99297ef8f397f3e09cf919719fc10f
[WebKit-https.git] / Source / WebCore / dom / make_names.pl
1 #!/usr/bin/perl -w
2
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.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 #
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. 
20 #
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.
31
32 use strict;
33 use FindBin;
34 use lib "$FindBin::Bin/../bindings/scripts";
35
36 use StaticString;
37 use Config;
38 use Getopt::Long;
39 use File::Path;
40 use File::Spec;
41 use IO::File;
42 use InFilesParser;
43
44 sub readTags($$);
45 sub readAttrs($$);
46
47 my $printFactory = 0; 
48 my $printWrapperFactory = 0; 
49 my $fontNamesIn = "";
50 my $tagsFile = "";
51 my $attrsFile = "";
52 my $outputDir = ".";
53 my %parsedTags = ();
54 my %parsedAttrs = ();
55 my %enabledTags = ();
56 my %enabledAttrs = ();
57 my %allTags = ();
58 my %allAttrs = ();
59 my %allStrings = ();
60 my %parameters = ();
61 my $extraDefines = 0;
62 my $initDefaults = 1;
63 my %extensionAttrs = ();
64
65 require Config;
66
67 my $ccLocation = "";
68 if ($ENV{CC}) {
69     $ccLocation = $ENV{CC};
70 } elsif ($Config::Config{"osname"} eq "darwin" && $ENV{SDKROOT}) {
71     chomp($ccLocation = `xcrun -find cc -sdk '$ENV{SDKROOT}'`);
72 } else {
73     $ccLocation = "/usr/bin/cc";
74 }
75
76 my $preprocessor = "";
77 if ($Config::Config{"osname"} eq "MSWin32") {
78     $preprocessor = "\"$ccLocation\" /EP";
79 } else {
80     $preprocessor = $ccLocation . " -E -x c++";
81 }
82
83 GetOptions(
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
92 );
93
94 mkpath($outputDir);
95
96 if (length($fontNamesIn)) {
97     my $names = new IO::File;
98     my $familyNamesFileBase = "WebKitFontFamily";
99
100     open($names, $fontNamesIn) or die "Failed to open file: $fontNamesIn";
101
102     $initDefaults = 0;
103     my $Parser = InFilesParser->new();
104     my $dummy;
105     $Parser->parse($names, \&parametersHandler, \&dummy);
106
107     my $F;
108     my $header = File::Spec->catfile($outputDir, "${familyNamesFileBase}Names.h");
109     open F, ">$header" or die "Unable to open $header for writing.";
110
111     printLicenseHeader($F);
112     printHeaderHead($F, "CSS", $familyNamesFileBase, "#include <wtf/text/AtomicString.h>", "");
113
114     printMacros($F, "extern const WTF::AtomicString", "", \%parameters);
115     print F "#endif\n\n";
116
117     printInit($F, 1);
118     close F;
119
120     my $source = File::Spec->catfile($outputDir, "${familyNamesFileBase}Names.cpp");
121     open F, ">$source" or die "Unable to open $source for writing.";
122
123     printLicenseHeader($F);
124     printCppHead($F, "CSS", $familyNamesFileBase, "WTF");
125
126     print F StaticString::GenerateStrings(\%parameters);
127
128     for my $name (sort keys %parameters) {
129         print F "DEFINE_GLOBAL(AtomicString, $name)\n";
130     }
131
132     printInit($F, 0);
133
134     print F "\n";
135     print F StaticString::GenerateStringAsserts(\%parameters);
136
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";
142     }
143
144     print F "}\n}\n}\n";
145     close F;
146     exit 0;
147 }
148
149 die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile));
150
151 if (length($tagsFile)) {
152     %allTags = %{readTags($tagsFile, 0)};
153     %enabledTags = %{readTags($tagsFile, 1)};
154     namesToStrings(\%allTags, \%allStrings);
155 }
156
157 if (length($attrsFile)) {
158     %allAttrs = %{readAttrs($attrsFile, 0)};
159     %enabledAttrs = %{readAttrs($attrsFile, 1)};
160     namesToStrings(\%allAttrs, \%allStrings);
161 }
162
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};
165
166 $parameters{namespacePrefix} = $parameters{namespace} unless $parameters{namespacePrefix};
167 $parameters{fallbackJSInterfaceName} = $parameters{fallbackInterfaceName} unless $parameters{fallbackJSInterfaceName};
168
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";
173
174 printNamesHeaderFile("$namesBasePath.h");
175 printNamesCppFile("$namesBasePath.cpp");
176 printTypeHelpersHeaderFile("$typeHelpersBasePath.h");
177
178 if ($printFactory) {
179     printFactoryCppFile("$factoryBasePath.cpp");
180     printFactoryHeaderFile("$factoryBasePath.h");
181 }
182
183 if ($printWrapperFactory) {
184     printWrapperFactoryCppFile($outputDir, $wrapperFactoryFileName);
185     printWrapperFactoryHeaderFile($outputDir, $wrapperFactoryFileName);
186 }
187
188 ### Hash initialization
189
190 sub defaultTagPropertyHash
191 {
192     return (
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,
202         'conditional' => 0,
203         'runtimeConditional' => 0,
204         'customTypeHelper' => 0,
205     );
206 }
207
208 sub defaultParametersHash
209 {
210     return (
211         'namespace' => '',
212         'namespacePrefix' => '',
213         'namespaceURI' => '',
214         'guardFactoryWith' => '',
215         'tagsNullNamespace' => 0,
216         'attrsNullNamespace' => 0,
217         'fallbackInterfaceName' => '',
218         'fallbackJSInterfaceName' => '',
219         'customElementInterfaceName' => '',
220     );
221 }
222
223 sub defaultInterfaceName
224 {
225     die "No namespace found" if !$parameters{namespace};
226     return $parameters{namespace} . upperCaseName($_[0]) . "Element"
227 }
228
229 ### Parsing handlers
230
231 sub valueForName
232 {
233     my $name = shift;
234     my $value = $extensionAttrs{$name};
235
236     if (!$value) {
237         $value = $name;
238         $value =~ s/_/-/g;
239     }
240
241     return $value;
242 }
243
244 sub namesToStrings
245 {
246     my $namesRef = shift;
247     my $stringsRef = shift;
248
249     my %names = %$namesRef;
250
251     for my $name (keys %names) {
252         $stringsRef->{$name} = valueForName($name);
253     }
254 }
255
256 sub tagsHandler
257 {
258     my ($tag, $property, $value) = @_;
259
260     $tag =~ s/-/_/g;
261
262     # Initialize default property values.
263     $parsedTags{$tag} = { defaultTagPropertyHash($tag) } if !defined($parsedTags{$tag});
264
265     if ($property) {
266         die "Unknown property $property for tag $tag\n" if !defined($parsedTags{$tag}{$property});
267
268         # The code relies on JSInterfaceName deriving from interfaceName to check for custom JSInterfaceName.
269         # So override JSInterfaceName if it was not already set.
270         $parsedTags{$tag}{JSInterfaceName} = $value if $property eq "interfaceName" && $parsedTags{$tag}{JSInterfaceName} eq $parsedTags{$tag}{interfaceName};
271
272         $parsedTags{$tag}{$property} = $value;
273     }
274 }
275
276 sub attrsHandler
277 {
278     my ($attr, $property, $value) = @_;
279     # Translate HTML5 extension attributes of the form 'x-webkit-feature' to 'webkitfeature'.
280     # We don't just check for the 'x-' prefix because there are attributes such as x-height
281     # which should follow the default path below.
282     if ($attr =~ m/^x-webkit-(.*)/) {
283         my $newAttr = "webkit$1";
284         $extensionAttrs{$newAttr} = $attr;
285         $attr = $newAttr;
286     }
287     $attr =~ s/-/_/g;
288
289     # Initialize default properties' values.
290     $parsedAttrs{$attr} = {} if !defined($parsedAttrs{$attr});
291
292     if ($property) {
293         die "Unknown property $property for attribute $attr\n" if !defined($parsedAttrs{$attr}{$property});
294         $parsedAttrs{$attr}{$property} = $value;
295     }
296 }
297
298 sub parametersHandler
299 {
300     my ($parameter, $value) = @_;
301
302     # Initialize default properties' values.
303     %parameters = defaultParametersHash() if (!(keys %parameters) && $initDefaults);
304
305     die "Unknown parameter $parameter for tags/attrs\n" if (!defined($parameters{$parameter}) && $initDefaults);
306     $parameters{$parameter} = $value;
307 }
308
309 ## Support routines
310
311 sub preprocessorCommand()
312 {
313     return $preprocessor if $extraDefines eq 0;
314     return $preprocessor . " -D" . join(" -D", split(" ", $extraDefines));
315 }
316
317 sub readNames($$$$)
318 {
319     my ($namesFile, $hashToFillRef, $handler, $usePreprocessor) = @_;
320
321     my $names = new IO::File;
322     if ($usePreprocessor) {
323         open($names, preprocessorCommand() . " " . $namesFile . "|") or die "Failed to open file: $namesFile";
324     } else {
325         open($names, $namesFile) or die "Failed to open file: $namesFile";
326     }
327
328     my $InParser = InFilesParser->new();
329     $InParser->parse($names, \&parametersHandler, $handler);
330
331     close($names);
332     die "Failed to read names from file: $namesFile" if (keys %{$hashToFillRef} == 0);
333     return $hashToFillRef;
334 }
335
336 sub readAttrs($$)
337 {
338     my ($namesFile, $usePreprocessor) = @_;
339     %parsedAttrs = ();
340     return readNames($namesFile, \%parsedAttrs, \&attrsHandler, $usePreprocessor);
341 }
342
343 sub readTags($$)
344 {
345     my ($namesFile, $usePreprocessor) = @_;
346     %parsedTags = ();
347     return readNames($namesFile, \%parsedTags, \&tagsHandler, $usePreprocessor);
348 }
349
350 sub printMacros
351 {
352     my ($F, $macro, $suffix, $namesRef) = @_;
353     my %names = %$namesRef;
354
355     for my $name (sort keys %names) {
356         print F "$macro $name","$suffix;\n";
357     }
358 }
359
360 sub usesDefaultWrapper
361 {
362     my $tagName = shift;
363     return $tagName eq $parameters{namespace} . "Element";
364 }
365
366 # Build a direct mapping from the tags to the Element to create.
367 sub buildConstructorMap
368 {
369     my %tagConstructorMap = ();
370     for my $tagName (keys %enabledTags) {
371         my $interfaceName = $enabledTags{$tagName}{interfaceName};
372
373         if ($enabledTags{$tagName}{mapToTagName}) {
374             die "Cannot handle multiple mapToTagName for $tagName\n" if $enabledTags{$enabledTags{$tagName}{mapToTagName}}{mapToTagName};
375             $interfaceName = $enabledTags{ $enabledTags{$tagName}{mapToTagName} }{interfaceName};
376         }
377
378         # Chop the string to keep the interesting part.
379         $interfaceName =~ s/$parameters{namespace}(.*)Element/$1/;
380         $tagConstructorMap{$tagName} = lc($interfaceName);
381     }
382
383     return %tagConstructorMap;
384 }
385
386 # Helper method that print the constructor's signature avoiding
387 # unneeded arguments.
388 sub printConstructorSignature
389 {
390     my ($F, $tagName, $constructorName, $constructorTagName) = @_;
391
392     print F "static Ref<$parameters{namespace}Element> ${constructorName}Constructor(const QualifiedName& $constructorTagName, Document& document";
393     if ($parameters{namespace} eq "HTML") {
394         print F ", HTMLFormElement*";
395         print F " formElement" if $enabledTags{$tagName}{constructorNeedsFormElement};
396     }
397     print F ", bool";
398     print F " createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser};
399     print F ")\n{\n";
400 }
401
402 # Helper method to dump the constructor interior and call the 
403 # Element constructor with the right arguments.
404 # The variable names should be kept in sync with the previous method.
405 sub printConstructorInterior
406 {
407     my ($F, $tagName, $interfaceName, $constructorTagName) = @_;
408
409     # Handle media elements.
410     # Note that wrapperOnlyIfMediaIsAvailable is a misnomer, because media availability
411     # does not just control the wrapper; it controls the element object that is created.
412     # FIXME: Could we instead do this entirely in the wrapper, and use custom wrappers
413     # instead of having all the support for this here in this script?
414     if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
415         print F <<END
416     if (!MediaPlayer::isAvailable() || !document.settings().mediaEnabled())
417         return $parameters{fallbackInterfaceName}::create($constructorTagName, document);
418     
419 END
420 ;
421     }
422
423     my $runtimeConditional = $enabledTags{$tagName}{runtimeConditional};
424     if ($runtimeConditional) {
425         print F <<END
426     if (!RuntimeEnabledFeatures::sharedFeatures().${runtimeConditional}Enabled())
427         return 0;
428 END
429 ;
430     }
431
432     my $settingsConditional = $enabledTags{$tagName}{settingsConditional};
433     if ($settingsConditional) {
434         print F <<END
435     if (!document.settings().${settingsConditional}())
436         return $parameters{fallbackInterfaceName}::create($constructorTagName, document);
437 END
438 ;
439     }
440
441     # Call the constructor with the right parameters.
442     print F "    return ${interfaceName}::create($constructorTagName, document";
443     print F ", formElement" if $enabledTags{$tagName}{constructorNeedsFormElement};
444     print F ", createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser};
445     print F ");\n}\n";
446 }
447
448 sub printConstructors
449 {
450     my ($F, $tagConstructorMapRef) = @_;
451     my %tagConstructorMap = %$tagConstructorMapRef;
452
453     # This is to avoid generating the same constructor several times.
454     my %uniqueTags = ();
455     for my $tagName (sort keys %tagConstructorMap) {
456         my $interfaceName = $enabledTags{$tagName}{interfaceName};
457
458         # Ignore the mapped tag
459         # FIXME: It could be moved inside this loop but was split for readibility.
460         next if (defined($uniqueTags{$interfaceName}) || $enabledTags{$tagName}{mapToTagName});
461         # Tags can have wrappers without constructors.
462         # This is useful to make user-agent shadow elements internally testable
463         # while keeping them from being avaialble in the HTML markup.
464         next if $enabledTags{$tagName}{noConstructor};
465
466         $uniqueTags{$interfaceName} = '1';
467
468         my $conditional = $enabledTags{$tagName}{conditional};
469         if ($conditional) {
470             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
471             print F "#if ${conditionalString}\n";
472         }
473
474         printConstructorSignature($F, $tagName, $tagConstructorMap{$tagName}, "tagName");
475         printConstructorInterior($F, $tagName, $interfaceName, "tagName");
476
477         if ($conditional) {
478             print F "#endif\n";
479         }
480
481         print F "\n";
482     }
483
484     # Mapped tag name uses a special wrapper to keep their prefix and namespaceURI while using the mapped localname.
485     for my $tagName (sort keys %tagConstructorMap) {
486         if ($enabledTags{$tagName}{mapToTagName}) {
487             my $mappedName = $enabledTags{$tagName}{mapToTagName};
488             printConstructorSignature($F, $mappedName, $mappedName . "To" . $tagName, "tagName");
489             printConstructorInterior($F, $mappedName, $enabledTags{$mappedName}{interfaceName}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())");
490         }
491     }
492 }
493
494 sub printFunctionTable
495 {
496     my ($F, $tagConstructorMap) = @_;
497     my %tagConstructorMap = %$tagConstructorMap;
498
499     for my $tagName (sort keys %tagConstructorMap) {
500         next if $enabledTags{$tagName}{noConstructor};
501
502         my $conditional = $enabledTags{$tagName}{conditional};
503         if ($conditional) {
504             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
505             print F "#if ${conditionalString}\n";
506         }
507
508         if ($enabledTags{$tagName}{mapToTagName}) {
509             print F "        { ${tagName}Tag, $enabledTags{$tagName}{mapToTagName}To${tagName}Constructor },\n";
510         } else {
511             print F "        { ${tagName}Tag, $tagConstructorMap{$tagName}Constructor },\n";
512         }
513
514         if ($conditional) {
515             print F "#endif\n";
516         }
517     }
518 }
519
520 sub svgCapitalizationHacks
521 {
522     my $name = shift;
523
524     $name = "FE" . ucfirst $1 if $name =~ /^fe(.+)$/;
525
526     return $name;
527 }
528
529 sub upperCaseName
530 {
531     my $name = shift;
532     
533     $name = svgCapitalizationHacks($name) if ($parameters{namespace} eq "SVG");
534
535     while ($name =~ /^(.*?)_(.*)/) {
536         $name = $1 . ucfirst $2;
537     }
538     
539     return ucfirst $name;
540 }
541
542 sub printHeaderHead
543 {
544     my ($F, $prefix, $namespace, $includes, $definitions) = @_;
545
546     print F<<END
547 #ifndef ${prefix}_${namespace}Names_h
548
549 #define ${prefix}_${namespace}Names_h
550
551 $includes
552
553 namespace WebCore {
554
555 ${definitions}namespace ${namespace}Names {
556
557 #ifndef ${prefix}_${namespace}_NAMES_HIDE_GLOBALS
558
559 END
560     ;
561 }
562
563 sub printCppHead
564 {
565     my ($F, $prefix, $namespace, $usedNamespace) = @_;
566
567     print F "#include \"config.h\"\n\n";
568     print F "#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n";
569     print F "#define ${prefix}_${namespace}_NAMES_HIDE_GLOBALS 1\n";
570     print F "#else\n";
571     print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n";
572     print F "#endif\n\n";
573
574     print F "#include \"${namespace}Names.h\"\n\n";
575     print F "#include <wtf/StaticConstructors.h>\n";
576
577     print F "namespace WebCore {\n\n";
578     print F "namespace ${namespace}Names {\n\n";
579     print F "using namespace $usedNamespace;\n\n";
580 }
581
582 sub printInit
583 {
584     my ($F, $isDefinition) = @_;
585
586     if ($isDefinition) {
587         print F "\nWEBCORE_EXPORT void init();\n\n";
588         print F "} }\n\n";
589         print F "#endif\n\n";
590         return;
591     }
592
593 print F "\nvoid init()
594 {
595     static bool initialized = false;
596     if (initialized)
597         return;
598     initialized = true;
599
600     // Use placement new to initialize the globals.
601
602     AtomicString::init();
603 ";
604 }
605
606 sub printLicenseHeader
607 {
608     my $F = shift;
609     print F "/*
610  * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
611  *
612  * This file was generated by the dom/make_names.pl script.
613  *
614  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc.  All rights reserved.
615  *
616  * Redistribution and use in source and binary forms, with or without
617  * modification, are permitted provided that the following conditions
618  * are met:
619  * 1. Redistributions of source code must retain the above copyright
620  *    notice, this list of conditions and the following disclaimer.
621  * 2. Redistributions in binary form must reproduce the above copyright
622  *    notice, this list of conditions and the following disclaimer in the
623  *    documentation and/or other materials provided with the distribution.
624  *
625  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
626  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
627  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
628  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
629  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
630  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
631  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
632  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
633  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
634  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
635  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
636  */
637
638 ";
639 }
640
641 sub printTypeHelpers
642 {
643     my ($F, $namesRef) = @_;
644     my %names = %$namesRef;
645
646     # Do a first pass to discard classes that map to several tags.
647     my %classToTags = ();
648     for my $name (keys %names) {
649         my $class = $parsedTags{$name}{interfaceName};
650         push(@{$classToTags{$class}}, $name) if defined $class;
651     }
652
653     for my $class (sort keys %classToTags) {
654         my $name = $classToTags{$class}[0];
655         next if $parsedTags{$name}{customTypeHelper};
656         # Skip classes that map to more than 1 tag.
657         my $tagCount = scalar @{$classToTags{$class}};
658         next if $tagCount > 1;
659
660         print F <<END
661 namespace WebCore {
662 class $class;
663 }
664 namespace WTF {
665 template <typename ArgType>
666 class TypeCastTraits<const WebCore::$class, ArgType, false /* isBaseType */> {
667 public:
668     static bool isOfType(ArgType& node) { return checkTagName(node); }
669 private:
670 END
671        ;
672        if ($parameters{namespace} eq "HTML" && ($parsedTags{$name}{wrapperOnlyIfMediaIsAvailable} || $parsedTags{$name}{settingsConditional})) {
673            print F <<END
674     static bool checkTagName(const WebCore::HTMLElement& element) { return !element.isHTMLUnknownElement() && element.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
675     static bool checkTagName(const WebCore::Node& node) { return is<WebCore::HTMLElement>(node) && checkTagName(downcast<WebCore::HTMLElement>(node)); }
676 END
677            ;
678        } else {
679            print F <<END
680     static bool checkTagName(const WebCore::$parameters{namespace}Element& element) { return element.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
681     static bool checkTagName(const WebCore::Node& node) { return node.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
682 END
683            ;
684        }
685        print F <<END
686 };
687 }
688 END
689        ;
690        print F "\n";
691     }
692 }
693
694 sub printTypeHelpersHeaderFile
695 {
696     my ($headerPath) = shift;
697     my $F;
698     open F, ">$headerPath";
699     printLicenseHeader($F);
700
701     print F "#ifndef ".$parameters{namespace}."ElementTypeHelpers_h\n";
702     print F "#define ".$parameters{namespace}."ElementTypeHelpers_h\n\n";
703     print F "#include \"".$parameters{namespace}."Names.h\"\n\n";
704
705     printTypeHelpers($F, \%allTags);
706
707     print F "#endif\n";
708
709     close F;
710 }
711
712 sub printNamesHeaderFile
713 {
714     my ($headerPath) = shift;
715     my $F;
716     open F, ">$headerPath";
717
718     printLicenseHeader($F);
719     printHeaderHead($F, "DOM", $parameters{namespace}, '#include "QualifiedName.h"', "class $parameters{namespace}QualifiedName : public QualifiedName { };\n\n");
720
721     my $lowercaseNamespacePrefix = lc($parameters{namespacePrefix});
722
723     print F "// Namespace\n";
724     print F "WEBCORE_EXPORT extern const WTF::AtomicString ${lowercaseNamespacePrefix}NamespaceURI;\n\n";
725
726     if (keys %allTags) {
727         print F "// Tags\n";
728         printMacros($F, "WEBCORE_EXPORT extern const WebCore::$parameters{namespace}QualifiedName", "Tag", \%allTags);
729     }
730
731     if (keys %allAttrs) {
732         print F "// Attributes\n";
733         printMacros($F, "WEBCORE_EXPORT extern const WebCore::QualifiedName", "Attr", \%allAttrs);
734     }
735     print F "#endif\n\n";
736
737     if (keys %allTags) {
738         print F "const unsigned $parameters{namespace}TagsCount = ", scalar(keys %allTags), ";\n";
739         print F "const WebCore::$parameters{namespace}QualifiedName* const* get$parameters{namespace}Tags();\n";
740     }
741
742     if (keys %allAttrs) {
743         print F "const unsigned $parameters{namespace}AttrsCount = ", scalar(keys %allAttrs), ";\n";
744         print F "const WebCore::QualifiedName* const* get$parameters{namespace}Attrs();\n";
745     }
746
747     printInit($F, 1);
748     close F;
749 }
750
751 sub printNamesCppFile
752 {
753     my $cppPath = shift;
754     my $F;
755     open F, ">$cppPath";
756     
757     printLicenseHeader($F);
758     printCppHead($F, "DOM", $parameters{namespace}, "WebCore");
759     
760     my $lowercaseNamespacePrefix = lc($parameters{namespacePrefix});
761
762     print F "WEBCORE_EXPORT DEFINE_GLOBAL(AtomicString, ${lowercaseNamespacePrefix}NamespaceURI)\n\n";
763
764     print F StaticString::GenerateStrings(\%allStrings);
765
766     if (keys %allTags) {
767         print F "// Tags\n";
768         for my $name (sort keys %allTags) {
769             print F "WEBCORE_EXPORT DEFINE_GLOBAL($parameters{namespace}QualifiedName, ", $name, "Tag)\n";
770         }
771         
772         print F "\n\nconst WebCore::$parameters{namespace}QualifiedName* const* get$parameters{namespace}Tags()\n";
773         print F "{\n    static const WebCore::$parameters{namespace}QualifiedName* const $parameters{namespace}Tags[] = {\n";
774         for my $name (sort keys %allTags) {
775             print F "        reinterpret_cast<const WebCore::$parameters{namespace}QualifiedName*>(&${name}Tag),\n";
776         }
777         print F "    };\n";
778         print F "    return $parameters{namespace}Tags;\n";
779         print F "}\n";
780     }
781
782     if (keys %allAttrs) {
783         print F "\n// Attributes\n";
784         for my $name (sort keys %allAttrs) {
785             print F "WEBCORE_EXPORT DEFINE_GLOBAL(QualifiedName, ", $name, "Attr)\n";
786         }
787         print F "\n\nconst WebCore::QualifiedName* const* get$parameters{namespace}Attrs()\n";
788         print F "{\n    static const WebCore::QualifiedName* const $parameters{namespace}Attrs[] = {\n";
789         for my $name (sort keys %allAttrs) {
790             print F "        reinterpret_cast<const WebCore::QualifiedName*>(&${name}Attr),\n";
791         }
792         print F "    };\n";
793         print F "    return $parameters{namespace}Attrs;\n";
794         print F "}\n";
795     }
796
797     printInit($F, 0);
798
799     print(F "    AtomicString ${lowercaseNamespacePrefix}NS(\"$parameters{namespaceURI}\", AtomicString::ConstructFromLiteral);\n\n");
800
801     print(F "    // Namespace\n");
802     print(F "    new (NotNull, (void*)&${lowercaseNamespacePrefix}NamespaceURI) AtomicString(${lowercaseNamespacePrefix}NS);\n");
803     print(F "\n");
804     print F StaticString::GenerateStringAsserts(\%allStrings);
805
806     if (keys %allTags) {
807         my $tagsNamespace = $parameters{tagsNullNamespace} ? "nullAtom()" : "${lowercaseNamespacePrefix}NS";
808         printDefinitions($F, \%allTags, "tags", $tagsNamespace);
809     }
810     if (keys %allAttrs) {
811         my $attrsNamespace = $parameters{attrsNullNamespace} ? "nullAtom()" : "${lowercaseNamespacePrefix}NS";
812         printDefinitions($F, \%allAttrs, "attributes", $attrsNamespace);
813     }
814
815     print F "}\n\n} }\n\n";
816     close F;
817 }
818
819 sub printJSElementIncludes
820 {
821     my $F = shift;
822
823     my %tagsSeen;
824     for my $tagName (sort keys %enabledTags) {
825         my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
826         next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName);
827         if ($enabledTags{$tagName}{conditional}) {
828             # We skip feature-define-specific #includes here since we handle them separately.
829             next;
830         }
831         $tagsSeen{$JSInterfaceName} = 1;
832
833         print F "#include \"JS${JSInterfaceName}.h\"\n";
834     }
835     print F "#include \"JS$parameters{fallbackJSInterfaceName}.h\"\n";
836 }
837
838 sub printElementIncludes
839 {
840     my $F = shift;
841
842     my %tagsSeen;
843     for my $tagName (sort keys %enabledTags) {
844         my $interfaceName = $enabledTags{$tagName}{interfaceName};
845         next if defined($tagsSeen{$interfaceName});
846         if ($enabledTags{$tagName}{conditional}) {
847             # We skip feature-define-specific #includes here since we handle them separately.
848             next;
849         }
850         $tagsSeen{$interfaceName} = 1;
851
852         print F "#include \"${interfaceName}.h\"\n";
853     }
854     print F "#include \"$parameters{fallbackInterfaceName}.h\"\n";
855 }
856
857 sub printConditionalElementIncludes
858 {
859     my ($F, $wrapperIncludes) = @_;
860
861     my %conditionals;
862     my %unconditionalElementIncludes;
863     my %unconditionalJSElementIncludes;
864
865     for my $tagName (keys %enabledTags) {
866         my $conditional = $enabledTags{$tagName}{conditional};
867         my $interfaceName = $enabledTags{$tagName}{interfaceName};
868         my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
869
870         if ($conditional) {
871             $conditionals{$conditional}{interfaceNames}{$interfaceName} = 1;
872             $conditionals{$conditional}{JSInterfaceNames}{$JSInterfaceName} = 1;
873         } else {
874             $unconditionalElementIncludes{$interfaceName} = 1;
875             $unconditionalJSElementIncludes{$JSInterfaceName} = 1;
876         }
877     }
878
879     for my $conditional (sort keys %conditionals) {
880         print F "\n#if ENABLE($conditional)\n";
881         for my $interfaceName (sort keys %{$conditionals{$conditional}{interfaceNames}}) {
882             next if $unconditionalElementIncludes{$interfaceName};
883             print F "#include \"$interfaceName.h\"\n";
884         }
885         if ($wrapperIncludes) {
886             for my $JSInterfaceName (sort keys %{$conditionals{$conditional}{JSInterfaceNames}}) {
887                 next if $unconditionalJSElementIncludes{$JSInterfaceName};
888                 print F "#include \"JS$JSInterfaceName.h\"\n";
889             }
890         }
891         print F "#endif\n";
892     }
893 }
894
895 sub printDefinitions
896 {
897     my ($F, $namesRef, $type, $namespaceURI) = @_;
898
899     my $shortCamelType = ucfirst(substr(substr($type, 0, -1), 0, 4));
900     my $capitalizedType = ucfirst($type);
901     
902 print F <<END
903
904     struct ${capitalizedType}TableEntry {
905         void* targetAddress;
906         StringImpl& name;
907     };
908
909     static const ${capitalizedType}TableEntry ${type}Table[] = {
910 END
911 ;
912     for my $name (sort keys %$namesRef) {
913         print F "        { (void*)&$name$shortCamelType, *reinterpret_cast<StringImpl*>(&${name}Data) },\n";
914     }
915
916 print F <<END
917     };
918
919     for (auto& entry : ${type}Table)
920 END
921 ;
922     if ($namespaceURI eq "nullAtom()") {
923         print F "        createQualifiedName(entry.targetAddress, &entry.name);\n";
924     } else {
925         print F "        createQualifiedName(entry.targetAddress, &entry.name, $namespaceURI);\n";
926     }
927 }
928
929 ## ElementFactory routines
930
931 sub printFactoryCppFile
932 {
933     my $cppPath = shift;
934     my $F;
935     open F, ">$cppPath";
936
937     my $formElementArgumentForDeclaration = "";
938     my $formElementArgumentForDefinition = "";
939     $formElementArgumentForDeclaration = ", HTMLFormElement*" if $parameters{namespace} eq "HTML";
940     $formElementArgumentForDefinition = ", HTMLFormElement* formElement" if $parameters{namespace} eq "HTML";
941
942     printLicenseHeader($F);
943
944     print F <<END
945 #include "config.h"
946 END
947     ;
948
949     print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
950
951     print F <<END
952 #include "$parameters{namespace}ElementFactory.h"
953
954 #include "$parameters{namespace}Names.h"
955
956 END
957     ;
958
959     printElementIncludes($F);
960     printConditionalElementIncludes($F, 0);
961
962     print F <<END
963
964 #include "Document.h"
965 #include "RuntimeEnabledFeatures.h"
966 #include "Settings.h"
967 #include <wtf/HashMap.h>
968 #include <wtf/NeverDestroyed.h>
969
970 namespace WebCore {
971
972 using namespace $parameters{namespace}Names;
973
974 typedef Ref<$parameters{namespace}Element> (*$parameters{namespace}ConstructorFunction)(const QualifiedName&, Document&$formElementArgumentForDeclaration, bool createdByParser);
975
976 END
977     ;
978
979     my %tagConstructorMap = buildConstructorMap();
980     my $argumentList;
981
982     if ($parameters{namespace} eq "HTML") {
983         $argumentList = "name, document, formElement, createdByParser";
984     } else {
985         $argumentList = "name, document, createdByParser";
986     }
987
988     my $lowercaseNamespacePrefix = lc($parameters{namespacePrefix});
989
990     printConstructors($F, \%tagConstructorMap);
991
992     print F <<END
993
994 struct ConstructorFunctionMapEntry {
995     ConstructorFunctionMapEntry($parameters{namespace}ConstructorFunction function, const QualifiedName& name)
996         : function(function)
997         , qualifiedName(&name)
998     { }
999
1000     ConstructorFunctionMapEntry()
1001         : function(nullptr)
1002         , qualifiedName(nullptr)
1003     { }
1004
1005     $parameters{namespace}ConstructorFunction function;
1006     const QualifiedName* qualifiedName; // Use pointer instead of reference so that emptyValue() in HashMap is cheap to create.
1007 };
1008
1009 static NEVER_INLINE HashMap<AtomicStringImpl*, ConstructorFunctionMapEntry> create$parameters{namespace}FactoryMap()
1010 {
1011     struct TableEntry {
1012         const QualifiedName& name;
1013         $parameters{namespace}ConstructorFunction function;
1014     };
1015
1016     static const TableEntry table[] = {
1017 END
1018     ;
1019
1020     printFunctionTable($F, \%tagConstructorMap);
1021
1022     print F <<END
1023     };
1024
1025     HashMap<AtomicStringImpl*, ConstructorFunctionMapEntry> map;
1026     for (auto& entry : table)
1027         map.add(entry.name.localName().impl(), ConstructorFunctionMapEntry(entry.function, entry.name));
1028     return map;
1029 }
1030
1031 static ConstructorFunctionMapEntry find$parameters{namespace}ElementConstructorFunction(const AtomicString& localName)
1032 {
1033     static const auto map = makeNeverDestroyed(create$parameters{namespace}FactoryMap());
1034     return map.get().get(localName.impl());
1035 }
1036
1037 RefPtr<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createKnownElement(const AtomicString& localName, Document& document$formElementArgumentForDefinition, bool createdByParser)
1038 {
1039     const ConstructorFunctionMapEntry& entry = find$parameters{namespace}ElementConstructorFunction(localName);
1040     if (LIKELY(entry.function)) {
1041         ASSERT(entry.qualifiedName);
1042         const auto& name = *entry.qualifiedName;
1043         return entry.function($argumentList);
1044     }
1045     return nullptr;
1046 }
1047
1048 RefPtr<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createKnownElement(const QualifiedName& name, Document& document$formElementArgumentForDefinition, bool createdByParser)
1049 {
1050     const ConstructorFunctionMapEntry& entry = find$parameters{namespace}ElementConstructorFunction(name.localName());
1051     if (LIKELY(entry.function))
1052         return entry.function($argumentList);
1053     return nullptr;
1054 }
1055
1056 Ref<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createElement(const AtomicString& localName, Document& document$formElementArgumentForDefinition, bool createdByParser)
1057 {
1058     const ConstructorFunctionMapEntry& entry = find$parameters{namespace}ElementConstructorFunction(localName);
1059     if (LIKELY(entry.function)) {
1060         ASSERT(entry.qualifiedName);
1061         const auto& name = *entry.qualifiedName;
1062         return entry.function($argumentList);
1063     }
1064     return $parameters{fallbackInterfaceName}::create(QualifiedName(nullAtom(), localName, ${lowercaseNamespacePrefix}NamespaceURI), document);
1065 }
1066
1067 Ref<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createElement(const QualifiedName& name, Document& document$formElementArgumentForDefinition, bool createdByParser)
1068 {
1069     const ConstructorFunctionMapEntry& entry = find$parameters{namespace}ElementConstructorFunction(name.localName());
1070     if (LIKELY(entry.function))
1071         return entry.function($argumentList);
1072     return $parameters{fallbackInterfaceName}::create(name, document);
1073 }
1074
1075 } // namespace WebCore
1076
1077 END
1078     ;
1079
1080     print F "#endif\n" if $parameters{guardFactoryWith};
1081
1082     close F;
1083 }
1084
1085 sub printFactoryHeaderFile
1086 {
1087     my $headerPath = shift;
1088     my $F;
1089     open F, ">$headerPath";
1090
1091     printLicenseHeader($F);
1092
1093     print F<<END
1094 #ifndef $parameters{namespace}ElementFactory_h
1095 #define $parameters{namespace}ElementFactory_h
1096
1097 #include <wtf/Forward.h>
1098
1099 namespace WebCore {
1100
1101 class Document;
1102 class HTMLFormElement;
1103 class QualifiedName;
1104
1105 class $parameters{namespace}Element;
1106
1107 class $parameters{namespace}ElementFactory {
1108 public:
1109 END
1110 ;
1111
1112 print F "static RefPtr<$parameters{namespace}Element> createKnownElement(const AtomicString&, Document&";
1113 print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
1114 print F ", bool createdByParser = false);\n";
1115
1116 print F "static RefPtr<$parameters{namespace}Element> createKnownElement(const QualifiedName&, Document&";
1117 print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
1118 print F ", bool createdByParser = false);\n";
1119
1120 print F "static Ref<$parameters{namespace}Element> createElement(const AtomicString&, Document&";
1121 print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
1122 print F ", bool createdByParser = false);\n";
1123
1124 print F "static Ref<$parameters{namespace}Element> createElement(const QualifiedName&, Document&";
1125 print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
1126 print F ", bool createdByParser = false);\n";
1127
1128 printf F<<END
1129 };
1130
1131 }
1132
1133 #endif // $parameters{namespace}ElementFactory_h
1134
1135 END
1136 ;
1137
1138     close F;
1139 }
1140
1141 ## Wrapper Factory routines
1142
1143 sub usesDefaultJSWrapper
1144 {
1145     my $name = shift;
1146
1147     # A tag reuses the default wrapper if its JSInterfaceName matches the default namespace Element.
1148     return $enabledTags{$name}{JSInterfaceName} eq $parameters{namespace} . "Element";
1149 }
1150
1151 sub printWrapperFunctions
1152 {
1153     my $F = shift;
1154
1155     my %tagsSeen;
1156     for my $tagName (sort keys %enabledTags) {
1157         # Avoid defining the same wrapper method twice.
1158         my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
1159         next if (defined($tagsSeen{$JSInterfaceName}) || (usesDefaultJSWrapper($tagName) && ($parameters{fallbackJSInterfaceName} eq $parameters{namespace} . "Element"))) && !$enabledTags{$tagName}{settingsConditional};
1160         $tagsSeen{$JSInterfaceName} = 1;
1161
1162         my $conditional = $enabledTags{$tagName}{conditional};
1163         if ($conditional) {
1164             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
1165             print F "#if ${conditionalString}\n\n";
1166         }
1167
1168         if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
1169             print F <<END
1170 static JSDOMObject* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, Ref<$parameters{namespace}Element>&& element)
1171 {
1172     if (element->is$parameters{fallbackInterfaceName}())
1173         return createWrapper<$parameters{fallbackInterfaceName}>(globalObject, WTFMove(element));
1174     return createWrapper<${JSInterfaceName}>(globalObject, WTFMove(element));
1175 }
1176
1177 END
1178             ;
1179         } elsif ($enabledTags{$tagName}{settingsConditional}) {
1180             print F <<END
1181 static JSDOMObject* create$enabledTags{$tagName}{interfaceName}Wrapper(JSDOMGlobalObject* globalObject, Ref<$parameters{namespace}Element>&& element)
1182 {
1183     if (element->is$parameters{fallbackInterfaceName}())
1184         return createWrapper<$parameters{fallbackInterfaceName}>(globalObject, WTFMove(element));
1185     return createWrapper<${JSInterfaceName}>(globalObject, WTFMove(element));
1186 }
1187
1188 END
1189             ;
1190         } elsif ($enabledTags{$tagName}{runtimeConditional}) {
1191             my $runtimeConditional = $enabledTags{$tagName}{runtimeConditional};
1192             print F <<END
1193 static JSDOMObject* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, Ref<$parameters{namespace}Element>&& element)
1194 {
1195     if (!RuntimeEnabledFeatures::sharedFeatures().${runtimeConditional}Enabled()) {
1196         ASSERT(element->is$parameters{fallbackInterfaceName}());
1197         return createWrapper<$parameters{fallbackJSInterfaceName}>(globalObject, WTFMove(element));
1198     }
1199
1200     return createWrapper<${JSInterfaceName}>(globalObject, WTFMove(element));
1201 }
1202 END
1203     ;
1204         } else {
1205             print F <<END
1206 static JSDOMObject* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, Ref<$parameters{namespace}Element>&& element)
1207 {
1208     return createWrapper<${JSInterfaceName}>(globalObject, WTFMove(element));
1209 }
1210
1211 END
1212     ;
1213         }
1214
1215         if ($conditional) {
1216             print F "#endif\n\n";
1217         }
1218     }
1219 }
1220
1221 sub printWrapperFactoryCppFile
1222 {
1223     my $outputDir = shift;
1224     my $wrapperFactoryFileName = shift;
1225     my $F;
1226     open F, ">" . $outputDir . "/JS" . $wrapperFactoryFileName . ".cpp";
1227
1228     printLicenseHeader($F);
1229
1230     print F "#include \"config.h\"\n";
1231     print F "#include \"JS$parameters{namespace}ElementWrapperFactory.h\"\n\n";
1232
1233     print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
1234
1235     printJSElementIncludes($F);
1236     printElementIncludes($F);
1237
1238     print F "\n#include \"$parameters{namespace}Names.h\"\n";
1239     print F <<END
1240
1241 #include "Document.h"
1242 #include "RuntimeEnabledFeatures.h"
1243 #include "Settings.h"
1244 #include <wtf/NeverDestroyed.h>
1245 #include <wtf/StdLibExtras.h>
1246 END
1247 ;
1248
1249     printConditionalElementIncludes($F, 1);
1250
1251     print F <<END
1252
1253 using namespace JSC;
1254
1255 namespace WebCore {
1256
1257 using namespace $parameters{namespace}Names;
1258
1259 typedef JSDOMObject* (*Create$parameters{namespace}ElementWrapperFunction)(JSDOMGlobalObject*, Ref<$parameters{namespace}Element>&&);
1260
1261 END
1262 ;
1263
1264     printWrapperFunctions($F);
1265
1266 print F <<END
1267
1268 static NEVER_INLINE HashMap<AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction> create$parameters{namespace}WrapperMap()
1269 {
1270     struct TableEntry {
1271         const QualifiedName& name;
1272         Create$parameters{namespace}ElementWrapperFunction function;
1273     };
1274
1275     static const TableEntry table[] = {
1276 END
1277 ;
1278
1279     for my $tag (sort keys %enabledTags) {
1280         # Do not add the name to the map if it does not have a JS wrapper constructor or uses the default wrapper.
1281         next if (usesDefaultJSWrapper($tag, \%enabledTags) && ($parameters{fallbackJSInterfaceName} eq $parameters{namespace} . "Element"));
1282
1283         my $conditional = $enabledTags{$tag}{conditional};
1284         if ($conditional) {
1285             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
1286             print F "#if ${conditionalString}\n";
1287         }
1288
1289         my $ucTag;
1290         if ($enabledTags{$tag}{settingsConditional}) {
1291             $ucTag = $enabledTags{$tag}{interfaceName};
1292         } else {
1293             $ucTag = $enabledTags{$tag}{JSInterfaceName};
1294         }
1295
1296         print F "        { ${tag}Tag, create${ucTag}Wrapper },\n";
1297
1298         if ($conditional) {
1299             print F "#endif\n";
1300         }
1301     }
1302
1303     print F <<END
1304     };
1305
1306     HashMap<AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction> map;
1307     for (auto& entry : table)
1308         map.add(entry.name.localName().impl(), entry.function);
1309     return map;
1310 }
1311
1312 JSDOMObject* createJS$parameters{namespace}Wrapper(JSDOMGlobalObject* globalObject, Ref<$parameters{namespace}Element>&& element)
1313 {
1314     static const auto functions = makeNeverDestroyed(create$parameters{namespace}WrapperMap());
1315     if (auto function = functions.get().get(element->localName().impl()))
1316         return function(globalObject, WTFMove(element));
1317 END
1318 ;
1319
1320     if ($parameters{customElementInterfaceName}) {
1321         print F <<END
1322     if (element->isCustomElementUpgradeCandidate())
1323         return createWrapper<$parameters{customElementInterfaceName}>(globalObject, WTFMove(element));
1324 END
1325 ;
1326     }
1327
1328     print F <<END
1329     return createWrapper<$parameters{fallbackJSInterfaceName}>(globalObject, WTFMove(element));
1330 }
1331
1332 }
1333 END
1334 ;
1335
1336     print F "\n#endif\n" if $parameters{guardFactoryWith};
1337
1338     close F;
1339 }
1340
1341 sub printWrapperFactoryHeaderFile
1342 {
1343     my $outputDir = shift;
1344     my $wrapperFactoryFileName = shift;
1345     my $F;
1346     open F, ">" . $outputDir . "/JS" . $wrapperFactoryFileName . ".h";
1347
1348     printLicenseHeader($F);
1349
1350     print F "#ifndef JS$parameters{namespace}ElementWrapperFactory_h\n";
1351     print F "#define JS$parameters{namespace}ElementWrapperFactory_h\n\n";
1352
1353     print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith};
1354
1355     print F <<END
1356 #include <wtf/Forward.h>
1357
1358 namespace WebCore {
1359
1360     class JSDOMObject;
1361     class JSDOMGlobalObject;
1362     class $parameters{namespace}Element;
1363
1364     JSDOMObject* createJS$parameters{namespace}Wrapper(JSDOMGlobalObject*, Ref<$parameters{namespace}Element>&&);
1365
1366 }
1367  
1368 END
1369     ;
1370
1371     print F "#endif // $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
1372
1373     print F "#endif // JS$parameters{namespace}ElementWrapperFactory_h\n";
1374
1375     close F;
1376 }