Rename JSDOMWrapper to JSDOMObject and JSDOMWrapperWithImplementation to JSDOMWrapper
[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
34 use StaticString;
35 use Config;
36 use Getopt::Long;
37 use File::Path;
38 use File::Spec;
39 use IO::File;
40 use InFilesParser;
41
42 sub readTags($$);
43 sub readAttrs($$);
44
45 my $printFactory = 0; 
46 my $printWrapperFactory = 0; 
47 my $fontNamesIn = "";
48 my $tagsFile = "";
49 my $attrsFile = "";
50 my $outputDir = ".";
51 my %parsedTags = ();
52 my %parsedAttrs = ();
53 my %enabledTags = ();
54 my %enabledAttrs = ();
55 my %allTags = ();
56 my %allAttrs = ();
57 my %allStrings = ();
58 my %parameters = ();
59 my $extraDefines = 0;
60 my $initDefaults = 1;
61 my %extensionAttrs = ();
62
63 require Config;
64
65 my $ccLocation = "";
66 if ($ENV{CC}) {
67     $ccLocation = $ENV{CC};
68 } elsif (($Config::Config{"osname"}) =~ /solaris/i) {
69     $ccLocation = "/usr/sfw/bin/gcc";
70 } elsif ($Config::Config{"osname"} eq "darwin" && $ENV{SDKROOT}) {
71     chomp($ccLocation = `xcrun -find cc -sdk '$ENV{SDKROOT}'`);
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     );
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     Settings* settings = document.settings();
416     if (!MediaPlayer::isAvailable() || (settings && !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     Settings* settings = document.settings();
436     if (!settings || !settings->${settingsConditional}())
437         return $parameters{fallbackInterfaceName}::create($constructorTagName, document);
438 END
439 ;
440     }
441
442     # Call the constructor with the right parameters.
443     print F "    return ${interfaceName}::create($constructorTagName, document";
444     print F ", formElement" if $enabledTags{$tagName}{constructorNeedsFormElement};
445     print F ", createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser};
446     print F ");\n}\n";
447 }
448
449 sub printConstructors
450 {
451     my ($F, $tagConstructorMapRef) = @_;
452     my %tagConstructorMap = %$tagConstructorMapRef;
453
454     # This is to avoid generating the same constructor several times.
455     my %uniqueTags = ();
456     for my $tagName (sort keys %tagConstructorMap) {
457         my $interfaceName = $enabledTags{$tagName}{interfaceName};
458
459         # Ignore the mapped tag
460         # FIXME: It could be moved inside this loop but was split for readibility.
461         next if (defined($uniqueTags{$interfaceName}) || $enabledTags{$tagName}{mapToTagName});
462         # Tags can have wrappers without constructors.
463         # This is useful to make user-agent shadow elements internally testable
464         # while keeping them from being avaialble in the HTML markup.
465         next if $enabledTags{$tagName}{noConstructor};
466
467         $uniqueTags{$interfaceName} = '1';
468
469         my $conditional = $enabledTags{$tagName}{conditional};
470         if ($conditional) {
471             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
472             print F "#if ${conditionalString}\n";
473         }
474
475         printConstructorSignature($F, $tagName, $tagConstructorMap{$tagName}, "tagName");
476         printConstructorInterior($F, $tagName, $interfaceName, "tagName");
477
478         if ($conditional) {
479             print F "#endif\n";
480         }
481
482         print F "\n";
483     }
484
485     # Mapped tag name uses a special wrapper to keep their prefix and namespaceURI while using the mapped localname.
486     for my $tagName (sort keys %tagConstructorMap) {
487         if ($enabledTags{$tagName}{mapToTagName}) {
488             my $mappedName = $enabledTags{$tagName}{mapToTagName};
489             printConstructorSignature($F, $mappedName, $mappedName . "To" . $tagName, "tagName");
490             printConstructorInterior($F, $mappedName, $enabledTags{$mappedName}{interfaceName}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())");
491         }
492     }
493 }
494
495 sub printFunctionTable
496 {
497     my ($F, $tagConstructorMap) = @_;
498     my %tagConstructorMap = %$tagConstructorMap;
499
500     for my $tagName (sort keys %tagConstructorMap) {
501         next if $enabledTags{$tagName}{noConstructor};
502
503         my $conditional = $enabledTags{$tagName}{conditional};
504         if ($conditional) {
505             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
506             print F "#if ${conditionalString}\n";
507         }
508
509         if ($enabledTags{$tagName}{mapToTagName}) {
510             print F "        { ${tagName}Tag, $enabledTags{$tagName}{mapToTagName}To${tagName}Constructor },\n";
511         } else {
512             print F "        { ${tagName}Tag, $tagConstructorMap{$tagName}Constructor },\n";
513         }
514
515         if ($conditional) {
516             print F "#endif\n";
517         }
518     }
519 }
520
521 sub svgCapitalizationHacks
522 {
523     my $name = shift;
524
525     $name = "FE" . ucfirst $1 if $name =~ /^fe(.+)$/;
526
527     return $name;
528 }
529
530 sub upperCaseName
531 {
532     my $name = shift;
533     
534     $name = svgCapitalizationHacks($name) if ($parameters{namespace} eq "SVG");
535
536     while ($name =~ /^(.*?)_(.*)/) {
537         $name = $1 . ucfirst $2;
538     }
539     
540     return ucfirst $name;
541 }
542
543 sub printHeaderHead
544 {
545     my ($F, $prefix, $namespace, $includes, $definitions) = @_;
546
547     print F<<END
548 #ifndef ${prefix}_${namespace}Names_h
549
550 #define ${prefix}_${namespace}Names_h
551
552 $includes
553
554 namespace WebCore {
555
556 ${definitions}namespace ${namespace}Names {
557
558 #ifndef ${prefix}_${namespace}_NAMES_HIDE_GLOBALS
559
560 END
561     ;
562 }
563
564 sub printCppHead
565 {
566     my ($F, $prefix, $namespace, $usedNamespace) = @_;
567
568     print F "#include \"config.h\"\n\n";
569     print F "#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n";
570     print F "#define ${prefix}_${namespace}_NAMES_HIDE_GLOBALS 1\n";
571     print F "#else\n";
572     print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n";
573     print F "#endif\n\n";
574
575     print F "#include \"${namespace}Names.h\"\n\n";
576     print F "#include <wtf/StaticConstructors.h>\n";
577
578     print F "namespace WebCore {\n\n";
579     print F "namespace ${namespace}Names {\n\n";
580     print F "using namespace $usedNamespace;\n\n";
581 }
582
583 sub printInit
584 {
585     my ($F, $isDefinition) = @_;
586
587     if ($isDefinition) {
588         print F "\nWEBCORE_EXPORT void init();\n\n";
589         print F "} }\n\n";
590         print F "#endif\n\n";
591         return;
592     }
593
594 print F "\nvoid init()
595 {
596     static bool initialized = false;
597     if (initialized)
598         return;
599     initialized = true;
600
601     // Use placement new to initialize the globals.
602
603     AtomicString::init();
604 ";
605 }
606
607 sub printLicenseHeader
608 {
609     my $F = shift;
610     print F "/*
611  * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
612  *
613  * This file was generated by the dom/make_names.pl script.
614  *
615  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc.  All rights reserved.
616  *
617  * Redistribution and use in source and binary forms, with or without
618  * modification, are permitted provided that the following conditions
619  * are met:
620  * 1. Redistributions of source code must retain the above copyright
621  *    notice, this list of conditions and the following disclaimer.
622  * 2. Redistributions in binary form must reproduce the above copyright
623  *    notice, this list of conditions and the following disclaimer in the
624  *    documentation and/or other materials provided with the distribution.
625  *
626  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
627  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
628  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
629  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
630  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
631  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
632  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
633  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
634  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
635  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
636  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
637  */
638
639 ";
640 }
641
642 sub printTypeHelpers
643 {
644     my ($F, $namesRef) = @_;
645     my %names = %$namesRef;
646
647     # Do a first pass to discard classes that map to several tags.
648     my %classToTags = ();
649     for my $name (keys %names) {
650         my $class = $parsedTags{$name}{interfaceName};
651         push(@{$classToTags{$class}}, $name) if defined $class;
652     }
653
654     for my $class (sort keys %classToTags) {
655         my $name = $classToTags{$class}[0];
656         next if $parsedTags{$name}{customTypeHelper};
657         # Skip classes that map to more than 1 tag.
658         my $tagCount = scalar @{$classToTags{$class}};
659         next if $tagCount > 1;
660
661         print F <<END
662 namespace WebCore {
663 class $class;
664 }
665 namespace WTF {
666 template <typename ArgType>
667 class TypeCastTraits<const WebCore::$class, ArgType, false /* isBaseType */> {
668 public:
669     static bool isOfType(ArgType& node) { return checkTagName(node); }
670 private:
671 END
672        ;
673        if ($parameters{namespace} eq "HTML" && ($parsedTags{$name}{wrapperOnlyIfMediaIsAvailable} || $parsedTags{$name}{settingsConditional})) {
674            print F <<END
675     static bool checkTagName(const WebCore::HTMLElement& element) { return !element.isHTMLUnknownElement() && element.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
676     static bool checkTagName(const WebCore::Node& node) { return is<WebCore::HTMLElement>(node) && checkTagName(downcast<WebCore::HTMLElement>(node)); }
677 END
678            ;
679        } else {
680            print F <<END
681     static bool checkTagName(const WebCore::$parameters{namespace}Element& element) { return element.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
682     static bool checkTagName(const WebCore::Node& node) { return node.hasTagName(WebCore::$parameters{namespace}Names::${name}Tag); }
683 END
684            ;
685        }
686        print F <<END
687 };
688 }
689 END
690        ;
691        print F "\n";
692     }
693 }
694
695 sub printTypeHelpersHeaderFile
696 {
697     my ($headerPath) = shift;
698     my $F;
699     open F, ">$headerPath";
700     printLicenseHeader($F);
701
702     print F "#ifndef ".$parameters{namespace}."ElementTypeHelpers_h\n";
703     print F "#define ".$parameters{namespace}."ElementTypeHelpers_h\n\n";
704     print F "#include \"".$parameters{namespace}."Names.h\"\n\n";
705
706     printTypeHelpers($F, \%allTags);
707
708     print F "#endif\n";
709
710     close F;
711 }
712
713 sub printNamesHeaderFile
714 {
715     my ($headerPath) = shift;
716     my $F;
717     open F, ">$headerPath";
718
719     printLicenseHeader($F);
720     printHeaderHead($F, "DOM", $parameters{namespace}, '#include "QualifiedName.h"', "class $parameters{namespace}QualifiedName : public QualifiedName { };\n\n");
721
722     my $lowercaseNamespacePrefix = lc($parameters{namespacePrefix});
723
724     print F "// Namespace\n";
725     print F "WEBCORE_EXPORT extern const WTF::AtomicString ${lowercaseNamespacePrefix}NamespaceURI;\n\n";
726
727     if (keys %allTags) {
728         print F "// Tags\n";
729         printMacros($F, "WEBCORE_EXPORT extern const WebCore::$parameters{namespace}QualifiedName", "Tag", \%allTags);
730     }
731
732     if (keys %allAttrs) {
733         print F "// Attributes\n";
734         printMacros($F, "WEBCORE_EXPORT extern 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 "WEBCORE_EXPORT DEFINE_GLOBAL(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 DEFINE_GLOBAL($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 DEFINE_GLOBAL(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 "    new (NotNull, (void*)&${lowercaseNamespacePrefix}NamespaceURI) AtomicString(${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         void* targetAddress;
907         StringImpl& name;
908     };
909
910     static const ${capitalizedType}TableEntry ${type}Table[] = {
911 END
912 ;
913     for my $name (sort keys %$namesRef) {
914         print F "        { (void*)&$name$shortCamelType, *reinterpret_cast<StringImpl*>(&${name}Data) },\n";
915     }
916
917 print F <<END
918     };
919
920     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(${type}Table); ++i)
921 END
922 ;
923     if ($namespaceURI eq "nullAtom") {
924         print F "        createQualifiedName(${type}Table[i].targetAddress, &${type}Table[i].name);\n";
925     } else {
926         print F "        createQualifiedName(${type}Table[i].targetAddress, &${type}Table[i].name, $namespaceURI);\n";
927     }
928 }
929
930 ## ElementFactory routines
931
932 sub printFactoryCppFile
933 {
934     my $cppPath = shift;
935     my $F;
936     open F, ">$cppPath";
937
938     my $formElementArgumentForDeclaration = "";
939     my $formElementArgumentForDefinition = "";
940     $formElementArgumentForDeclaration = ", HTMLFormElement*" if $parameters{namespace} eq "HTML";
941     $formElementArgumentForDefinition = ", HTMLFormElement* formElement" if $parameters{namespace} eq "HTML";
942
943     printLicenseHeader($F);
944
945     print F <<END
946 #include "config.h"
947 END
948     ;
949
950     print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
951
952     print F <<END
953 #include "$parameters{namespace}ElementFactory.h"
954
955 #include "$parameters{namespace}Names.h"
956
957 END
958     ;
959
960     printElementIncludes($F);
961     printConditionalElementIncludes($F, 0);
962
963     print F <<END
964
965 #include "Document.h"
966 #include "RuntimeEnabledFeatures.h"
967 #include "Settings.h"
968 #include <wtf/HashMap.h>
969 #include <wtf/NeverDestroyed.h>
970
971 namespace WebCore {
972
973 using namespace $parameters{namespace}Names;
974
975 typedef Ref<$parameters{namespace}Element> (*$parameters{namespace}ConstructorFunction)(const QualifiedName&, Document&$formElementArgumentForDeclaration, bool createdByParser);
976
977 END
978     ;
979
980     my %tagConstructorMap = buildConstructorMap();
981
982     printConstructors($F, \%tagConstructorMap);
983
984     print F <<END
985 static NEVER_INLINE void populate$parameters{namespace}FactoryMap(HashMap<AtomicStringImpl*, $parameters{namespace}ConstructorFunction>& map)
986 {
987     struct TableEntry {
988         const QualifiedName& name;
989         $parameters{namespace}ConstructorFunction function;
990     };
991
992     static const TableEntry table[] = {
993 END
994     ;
995
996     printFunctionTable($F, \%tagConstructorMap);
997
998     print F <<END
999     };
1000
1001     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(table); ++i)
1002         map.add(table[i].name.localName().impl(), table[i].function);
1003 }
1004
1005 Ref<$parameters{namespace}Element> $parameters{namespace}ElementFactory::createElement(const QualifiedName& name, Document& document$formElementArgumentForDefinition, bool createdByParser)
1006 {
1007     static NeverDestroyed<HashMap<AtomicStringImpl*, $parameters{namespace}ConstructorFunction>> functions;
1008     if (functions.get().isEmpty())
1009         populate$parameters{namespace}FactoryMap(functions);
1010     if ($parameters{namespace}ConstructorFunction function = functions.get().get(name.localName().impl()))
1011 END
1012     ;
1013
1014     if ($parameters{namespace} eq "HTML") {
1015         print F "        return function(name, document, formElement, createdByParser);\n";
1016     } else {
1017         print F "        return function(name, document, createdByParser);\n";
1018     }
1019
1020     print F <<END
1021     return $parameters{fallbackInterfaceName}::create(name, document);
1022 }
1023
1024 } // namespace WebCore
1025
1026 END
1027     ;
1028
1029     print F "#endif\n" if $parameters{guardFactoryWith};
1030
1031     close F;
1032 }
1033
1034 sub printFactoryHeaderFile
1035 {
1036     my $headerPath = shift;
1037     my $F;
1038     open F, ">$headerPath";
1039
1040     printLicenseHeader($F);
1041
1042     print F<<END
1043 #ifndef $parameters{namespace}ElementFactory_h
1044 #define $parameters{namespace}ElementFactory_h
1045
1046 #include <wtf/Forward.h>
1047
1048 namespace WebCore {
1049
1050     class Document;
1051     class HTMLFormElement;
1052     class QualifiedName;
1053
1054     class $parameters{namespace}Element;
1055
1056     class $parameters{namespace}ElementFactory {
1057     public:
1058 END
1059 ;
1060
1061 print F "        static Ref<$parameters{namespace}Element> createElement(const QualifiedName&, Document&";
1062 print F ", HTMLFormElement* = nullptr" if $parameters{namespace} eq "HTML";
1063 print F ", bool createdByParser = false);\n";
1064
1065 printf F<<END
1066     };
1067 }
1068
1069 #endif // $parameters{namespace}ElementFactory_h
1070
1071 END
1072 ;
1073
1074     close F;
1075 }
1076
1077 ## Wrapper Factory routines
1078
1079 sub usesDefaultJSWrapper
1080 {
1081     my $name = shift;
1082
1083     # A tag reuses the default wrapper if its JSInterfaceName matches the default namespace Element.
1084     return $enabledTags{$name}{JSInterfaceName} eq $parameters{namespace} . "Element";
1085 }
1086
1087 sub printWrapperFunctions
1088 {
1089     my $F = shift;
1090
1091     my %tagsSeen;
1092     for my $tagName (sort keys %enabledTags) {
1093         # Avoid defining the same wrapper method twice.
1094         my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
1095         next if (defined($tagsSeen{$JSInterfaceName}) || (usesDefaultJSWrapper($tagName) && ($parameters{fallbackJSInterfaceName} eq $parameters{namespace} . "Element"))) && !$enabledTags{$tagName}{settingsConditional};
1096         $tagsSeen{$JSInterfaceName} = 1;
1097
1098         my $conditional = $enabledTags{$tagName}{conditional};
1099         if ($conditional) {
1100             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
1101             print F "#if ${conditionalString}\n\n";
1102         }
1103
1104         if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
1105             print F <<END
1106 static JSDOMObject* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1107 {
1108     if (element->is$parameters{fallbackInterfaceName}())
1109         return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackInterfaceName}, element.get());
1110     return CREATE_DOM_WRAPPER(globalObject, ${JSInterfaceName}, element.get());
1111 }
1112
1113 END
1114             ;
1115         } elsif ($enabledTags{$tagName}{settingsConditional}) {
1116             print F <<END
1117 static JSDOMObject* create$enabledTags{$tagName}{interfaceName}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1118 {
1119     if (element->is$parameters{fallbackInterfaceName}())
1120         return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackInterfaceName}, element.get());
1121     return CREATE_DOM_WRAPPER(globalObject, ${JSInterfaceName}, element.get());
1122 }
1123
1124 END
1125             ;
1126         } elsif ($enabledTags{$tagName}{runtimeConditional}) {
1127             my $runtimeConditional = $enabledTags{$tagName}{runtimeConditional};
1128             print F <<END
1129 static JSDOMObject* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1130 {
1131     if (!RuntimeEnabledFeatures::sharedFeatures().${runtimeConditional}Enabled()) {
1132         ASSERT(!element || element->is$parameters{fallbackInterfaceName}());
1133         return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackJSInterfaceName}, element.get());
1134     }
1135
1136     return CREATE_DOM_WRAPPER(globalObject, ${JSInterfaceName}, element.get());
1137 }
1138 END
1139     ;
1140         } else {
1141             print F <<END
1142 static JSDOMObject* create${JSInterfaceName}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1143 {
1144     return CREATE_DOM_WRAPPER(globalObject, ${JSInterfaceName}, element.get());
1145 }
1146
1147 END
1148     ;
1149         }
1150
1151         if ($conditional) {
1152             print F "#endif\n\n";
1153         }
1154     }
1155 }
1156
1157 sub printWrapperFactoryCppFile
1158 {
1159     my $outputDir = shift;
1160     my $wrapperFactoryFileName = shift;
1161     my $F;
1162     open F, ">" . $outputDir . "/JS" . $wrapperFactoryFileName . ".cpp";
1163
1164     printLicenseHeader($F);
1165
1166     print F "#include \"config.h\"\n";
1167     print F "#include \"JS$parameters{namespace}ElementWrapperFactory.h\"\n\n";
1168
1169     print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
1170
1171     printJSElementIncludes($F);
1172     printElementIncludes($F);
1173
1174     print F "\n#include \"$parameters{namespace}Names.h\"\n";
1175     print F <<END
1176
1177 #include "Document.h"
1178 #include "RuntimeEnabledFeatures.h"
1179 #include "Settings.h"
1180 #include <wtf/NeverDestroyed.h>
1181 #include <wtf/StdLibExtras.h>
1182 END
1183 ;
1184
1185     printConditionalElementIncludes($F, 1);
1186
1187     print F <<END
1188
1189 using namespace JSC;
1190
1191 namespace WebCore {
1192
1193 using namespace $parameters{namespace}Names;
1194
1195 typedef JSDOMObject* (*Create$parameters{namespace}ElementWrapperFunction)(JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>);
1196
1197 END
1198 ;
1199
1200     printWrapperFunctions($F);
1201
1202 print F <<END
1203
1204 static NEVER_INLINE void populate$parameters{namespace}WrapperMap(HashMap<AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction>& map)
1205 {
1206     struct TableEntry {
1207         const QualifiedName& name;
1208         Create$parameters{namespace}ElementWrapperFunction function;
1209     };
1210
1211     static const TableEntry table[] = {
1212 END
1213 ;
1214
1215     for my $tag (sort keys %enabledTags) {
1216         # Do not add the name to the map if it does not have a JS wrapper constructor or uses the default wrapper.
1217         next if (usesDefaultJSWrapper($tag, \%enabledTags) && ($parameters{fallbackJSInterfaceName} eq $parameters{namespace} . "Element"));
1218
1219         my $conditional = $enabledTags{$tag}{conditional};
1220         if ($conditional) {
1221             my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
1222             print F "#if ${conditionalString}\n";
1223         }
1224
1225         my $ucTag;
1226         if ($enabledTags{$tag}{settingsConditional}) {
1227             $ucTag = $enabledTags{$tag}{interfaceName};
1228         } else {
1229             $ucTag = $enabledTags{$tag}{JSInterfaceName};
1230         }
1231
1232         # FIXME Remove unnecessary '&' from the following (print) line once we switch to a non-broken Visual Studio compiler.
1233         # https://bugs.webkit.org/show_bug.cgi?id=121235:
1234         print F "        { ${tag}Tag, &create${ucTag}Wrapper },\n";
1235
1236         if ($conditional) {
1237             print F "#endif\n";
1238         }
1239     }
1240
1241     print F <<END
1242     };
1243
1244     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(table); ++i)
1245         map.add(table[i].name.localName().impl(), table[i].function);
1246 }
1247
1248 JSDOMObject* createJS$parameters{namespace}Wrapper(JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
1249 {
1250     static NeverDestroyed<HashMap<AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction>> functions;
1251     if (functions.get().isEmpty())
1252         populate$parameters{namespace}WrapperMap(functions);
1253     if (auto function = functions.get().get(element->localName().impl()))
1254         return function(globalObject, element);
1255     return CREATE_DOM_WRAPPER(globalObject, $parameters{fallbackJSInterfaceName}, element.get());
1256 }
1257
1258 }
1259 END
1260 ;
1261
1262     print F "\n#endif\n" if $parameters{guardFactoryWith};
1263
1264     close F;
1265 }
1266
1267 sub printWrapperFactoryHeaderFile
1268 {
1269     my $outputDir = shift;
1270     my $wrapperFactoryFileName = shift;
1271     my $F;
1272     open F, ">" . $outputDir . "/JS" . $wrapperFactoryFileName . ".h";
1273
1274     printLicenseHeader($F);
1275
1276     print F "#ifndef JS$parameters{namespace}ElementWrapperFactory_h\n";
1277     print F "#define JS$parameters{namespace}ElementWrapperFactory_h\n\n";
1278
1279     print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith};
1280
1281     print F <<END
1282 #include <wtf/Forward.h>
1283
1284 namespace WebCore {
1285
1286     class JSDOMObject;
1287     class JSDOMGlobalObject;
1288     class $parameters{namespace}Element;
1289
1290     JSDOMObject* createJS$parameters{namespace}Wrapper(JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>);
1291
1292 }
1293  
1294 END
1295     ;
1296
1297     print F "#endif // $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
1298
1299     print F "#endif // JS$parameters{namespace}ElementWrapperFactory_h\n";
1300
1301     close F;
1302 }