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