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