2 # Copyright (C) 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013, 2014 Apple Inc. All rights reserved.
7 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
8 # Copyright (C) Research In Motion Limited 2010. All rights reserved.
9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
10 # Copyright (C) 2011 Patrick Gansterer <paroga@webkit.org>
11 # Copyright (C) 2012 Ericsson AB. All rights reserved.
12 # Copyright (C) 2007, 2008, 2009, 2012 Google Inc.
13 # Copyright (C) 2013 Samsung Electronics. All rights reserved.
15 # This library is free software; you can redistribute it and/or
16 # modify it under the terms of the GNU Library General Public
17 # License as published by the Free Software Foundation; either
18 # version 2 of the License, or (at your option) any later version.
20 # This library is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 # Library General Public License for more details.
25 # You should have received a copy of the GNU Library General Public License
26 # along with this library; see the file COPYING.LIB. If not, write to
27 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 # Boston, MA 02110-1301, USA.
31 package CodeGeneratorJS;
34 use constant FileNamePrefix => "JS";
39 my $writeDependencies = 0;
41 my @headerContentHeader = ();
42 my @headerContent = ();
43 my %headerIncludes = ();
44 my %headerTrailingIncludes = ();
46 my @implContentHeader = ();
48 my %implIncludes = ();
50 my $numCachedAttributes = 0;
51 my $currentCachedAttribute = 0;
53 my $beginAppleCopyrightForHeaderFiles = <<END;
54 // ------- Begin Apple Copyright -------
56 * Copyright (C) 2008, Apple Inc. All rights reserved.
58 * Permission is granted by Apple to use this file to the extent
59 * necessary to relink with LGPL WebKit files.
61 * No license or rights are granted by Apple expressly or by
62 * implication, estoppel, or otherwise, to Apple patents and
63 * trademarks. For the sake of clarity, no license or rights are
64 * granted by Apple expressly or by implication, estoppel, or otherwise,
65 * under any Apple patents, copyrights and trademarks to underlying
66 * implementations of any application programming interfaces (APIs)
67 * or to any functionality that is invoked by calling any API.
71 my $beginAppleCopyrightForSourceFiles = <<END;
72 // ------- Begin Apple Copyright -------
74 * Copyright (C) 2008, Apple Inc. All rights reserved.
76 * No license or rights are granted by Apple expressly or by implication,
77 * estoppel, or otherwise, to Apple copyrights, patents, trademarks, trade
78 * secrets or other rights.
82 my $endAppleCopyright = <<END;
83 // ------- End Apple Copyright -------
88 my $headerTemplate = << "EOF";
90 This file is part of the WebKit open source project.
91 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
93 This library is free software; you can redistribute it and/or
94 modify it under the terms of the GNU Library General Public
95 License as published by the Free Software Foundation; either
96 version 2 of the License, or (at your option) any later version.
98 This library is distributed in the hope that it will be useful,
99 but WITHOUT ANY WARRANTY; without even the implied warranty of
100 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
101 Library General Public License for more details.
103 You should have received a copy of the GNU Library General Public License
104 along with this library; see the file COPYING.LIB. If not, write to
105 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
106 Boston, MA 02110-1301, USA.
110 # Default constructor
116 $codeGenerator = shift;
117 shift; # $useLayerOnTop
118 shift; # $preprocessor
119 $writeDependencies = shift;
121 bless($reference, $object);
125 sub GenerateInterface
128 my $interface = shift;
131 $codeGenerator->LinkOverloadedFunctions($interface);
133 # Start actual generation
134 if ($interface->isCallback) {
135 $object->GenerateCallbackHeader($interface);
136 $object->GenerateCallbackImplementation($interface);
138 $object->GenerateHeader($interface);
139 $object->GenerateImplementation($interface);
143 sub GenerateAttributeEventListenerCall
145 my $implSetterFunctionName = shift;
146 my $windowEventListener = shift;
148 my $wrapperObject = $windowEventListener ? "globalObject" : "castedThis";
149 my @GenerateEventListenerImpl = ();
151 push(@GenerateEventListenerImpl, " impl.set$implSetterFunctionName(createJSEventListenerForAttribute(*exec, value, *$wrapperObject));\n");
152 return @GenerateEventListenerImpl;
155 sub GenerateEventListenerCall
157 my $functionName = shift;
158 my $suffix = ucfirst $functionName;
159 my $passRefPtrHandling = ($functionName eq "add") ? "" : ".ptr()";
161 $implIncludes{"JSEventListener.h"} = 1;
163 my @GenerateEventListenerImpl = ();
165 push(@GenerateEventListenerImpl, <<END);
166 JSValue listener = exec->argument(1);
167 if (UNLIKELY(!listener.isObject()))
168 return JSValue::encode(jsUndefined());
169 impl.${functionName}EventListener(exec->argument(0).toString(exec)->toAtomicString(exec), createJSEventListenerFor$suffix(*exec, *asObject(listener), *castedThis)$passRefPtrHandling, exec->argument(2).toBoolean(exec));
170 return JSValue::encode(jsUndefined());
172 return @GenerateEventListenerImpl;
175 sub GetParentClassName
177 my $interface = shift;
179 return $interface->extendedAttributes->{"JSLegacyParent"} if $interface->extendedAttributes->{"JSLegacyParent"};
180 return "JSDOMWrapper" unless $interface->parent;
181 return "JS" . $interface->parent;
184 sub GetCallbackClassName
186 my $className = shift;
188 return "JS$className";
191 sub AddIncludesForTypeInImpl
194 my $isCallback = @_ ? shift : 0;
196 AddIncludesForType($type, $isCallback, \%implIncludes);
199 sub AddIncludesForTypeInHeader
202 my $isCallback = @_ ? shift : 0;
204 AddIncludesForType($type, $isCallback, \%headerIncludes);
207 my %typesWithoutHeader = (
214 sub SkipIncludeHeader
218 return 1 if $codeGenerator->SkipIncludeHeader($type);
219 return $typesWithoutHeader{$type};
222 sub AddIncludesForType
225 my $isCallback = shift;
226 my $includesRef = shift;
228 return if SkipIncludeHeader($type);
230 # When we're finished with the one-file-per-class
231 # reorganization, we won't need these special cases.
232 if ($type eq "XPathNSResolver") {
233 $includesRef->{"JSXPathNSResolver.h"} = 1;
234 $includesRef->{"JSCustomXPathNSResolver.h"} = 1;
235 } elsif ($isCallback && $codeGenerator->IsWrapperType($type)) {
236 $includesRef->{"JS${type}.h"} = 1;
237 } elsif ($codeGenerator->GetSequenceType($type) or $codeGenerator->GetArrayType($type)) {
238 my $arrayType = $codeGenerator->GetArrayType($type);
239 my $sequenceType = $codeGenerator->GetSequenceType($type);
240 my $arrayOrSequenceType = $arrayType || $sequenceType;
242 if ($arrayType eq "DOMString") {
243 $includesRef->{"JSDOMStringList.h"} = 1;
244 $includesRef->{"DOMStringList.h"} = 1;
245 } elsif ($codeGenerator->IsRefPtrType($arrayOrSequenceType)) {
246 $includesRef->{"JS${arrayOrSequenceType}.h"} = 1;
247 $includesRef->{"${arrayOrSequenceType}.h"} = 1;
249 $includesRef->{"<runtime/JSArray.h>"} = 1;
251 # default, include the same named file
252 $includesRef->{"${type}.h"} = 1;
256 sub AddToImplIncludes
259 my $conditional = shift;
261 if (not $conditional) {
262 $implIncludes{$header} = 1;
263 } elsif (not exists($implIncludes{$header})) {
264 $implIncludes{$header} = $conditional;
266 my $oldValue = $implIncludes{$header};
267 if ($oldValue ne 1) {
269 $newValue{$conditional} = 1;
270 foreach my $condition (split(/\|/, $oldValue)) {
271 $newValue{$condition} = 1;
273 $implIncludes{$header} = join("|", sort keys %newValue);
278 sub IsScriptProfileType
281 return 1 if ($type eq "ScriptProfileNode");
287 my $attribute = shift;
288 return $attribute->isReadOnly && !$attribute->signature->extendedAttributes->{"Replaceable"};
291 sub AddTypedefForScriptProfileType
294 (my $jscType = $type) =~ s/Script//;
296 push(@headerContent, "typedef JSC::$jscType $type;\n\n");
299 sub AddClassForwardIfNeeded
301 my $interfaceName = shift;
303 # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them!
304 unless ($codeGenerator->IsSVGAnimatedType($interfaceName) or IsScriptProfileType($interfaceName) or $codeGenerator->IsTypedArrayType($interfaceName)) {
305 push(@headerContent, "class $interfaceName;\n\n");
306 # ScriptProfile and ScriptProfileNode are typedefs to JSC::Profile and JSC::ProfileNode.
307 } elsif (IsScriptProfileType($interfaceName)) {
308 $headerIncludes{"<profiler/ProfileNode.h>"} = 1;
309 AddTypedefForScriptProfileType($interfaceName);
313 sub GetGenerateIsReachable
315 my $interface = shift;
316 return $interface->extendedAttributes->{"GenerateIsReachable"};
319 sub GetCustomIsReachable
321 my $interface = shift;
322 return $interface->extendedAttributes->{"CustomIsReachable"};
325 sub IsDOMGlobalObject
327 my $interface = shift;
328 return $interface->name eq "DOMWindow" || $codeGenerator->InheritsInterface($interface, "WorkerGlobalScope");
331 sub GenerateGetOwnPropertySlotBody
333 my ($interface, $interfaceName, $className, $hasAttributes, $inlined) = @_;
335 my $namespaceMaybe = ($inlined ? "JSC::" : "");
336 my $namedGetterFunction = GetNamedGetterFunction($interface);
337 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
339 my @getOwnPropertySlotImpl = ();
341 if ($interfaceName eq "NamedNodeMap" or $interfaceName =~ /^HTML\w*Collection$/) {
342 push(@getOwnPropertySlotImpl, " ${namespaceMaybe}JSValue proto = thisObject->prototype();\n");
343 push(@getOwnPropertySlotImpl, " if (proto.isObject() && jsCast<${namespaceMaybe}JSObject*>(proto)->hasProperty(exec, propertyName))\n");
344 push(@getOwnPropertySlotImpl, " return false;\n\n");
347 my $manualLookupGetterGeneration = sub {
348 my $requiresManualLookup = $indexedGetterFunction || $namedGetterFunction;
349 if ($requiresManualLookup) {
350 push(@getOwnPropertySlotImpl, " const ${namespaceMaybe}HashTableValue* entry = getStaticValueSlotEntryWithoutCaching<$className>(exec, propertyName);\n");
351 push(@getOwnPropertySlotImpl, " if (entry) {\n");
352 push(@getOwnPropertySlotImpl, " slot.setCacheableCustom(thisObject, entry->attributes(), entry->propertyGetter());\n");
353 push(@getOwnPropertySlotImpl, " return true;\n");
354 push(@getOwnPropertySlotImpl, " }\n");
358 if (!$interface->extendedAttributes->{"CustomNamedGetter"} and InstanceAttributeCount($interface) > 0) {
359 &$manualLookupGetterGeneration();
362 if ($indexedGetterFunction) {
363 push(@getOwnPropertySlotImpl, " unsigned index = propertyName.asIndex();\n");
365 # If the item function returns a string then we let the TreatReturnedNullStringAs handle the cases
366 # where the index is out of range.
367 if ($indexedGetterFunction->signature->type eq "DOMString") {
368 push(@getOwnPropertySlotImpl, " if (index != PropertyName::NotAnIndex) {\n");
370 push(@getOwnPropertySlotImpl, " if (index != PropertyName::NotAnIndex && index < thisObject->impl().length()) {\n");
372 # Assume that if there's a setter, the index will be writable
373 if ($interface->extendedAttributes->{"CustomIndexedSetter"}) {
374 push(@getOwnPropertySlotImpl, " unsigned attributes = ${namespaceMaybe}DontDelete;\n");
376 push(@getOwnPropertySlotImpl, " unsigned attributes = ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly;\n");
378 push(@getOwnPropertySlotImpl, " slot.setValue(thisObject, attributes, " . GetIndexedGetterExpression($indexedGetterFunction) . ");\n");
379 push(@getOwnPropertySlotImpl, " return true;\n");
380 push(@getOwnPropertySlotImpl, " }\n");
383 if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) {
384 push(@getOwnPropertySlotImpl, " if (canGetItemsForName(exec, &thisObject->impl(), propertyName)) {\n");
385 push(@getOwnPropertySlotImpl, " slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, thisObject->nameGetter);\n");
386 push(@getOwnPropertySlotImpl, " return true;\n");
387 push(@getOwnPropertySlotImpl, " }\n");
389 $headerIncludes{"wtf/text/AtomicString.h"} = 1;
391 $implIncludes{"wtf/text/AtomicString.h"} = 1;
395 if ($interface->extendedAttributes->{"CustomNamedGetter"}) {
396 &$manualLookupGetterGeneration();
399 if ($interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) {
400 push(@getOwnPropertySlotImpl, " if (thisObject->getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
401 push(@getOwnPropertySlotImpl, " return true;\n");
404 if ($hasAttributes) {
406 push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, *info()->staticPropHashTable, thisObject, propertyName, slot);\n");
408 push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, ${className}Table, thisObject, propertyName, slot);\n");
411 push(@getOwnPropertySlotImpl, " return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);\n");
414 return @getOwnPropertySlotImpl;
417 sub GenerateHeaderContentHeader
419 my $interface = shift;
420 my $className = "JS" . $interface->name;
422 my @headerContentHeader;
423 if ($interface->extendedAttributes->{"AppleCopyright"}) {
424 @headerContentHeader = split("\r", $beginAppleCopyrightForHeaderFiles);
426 @headerContentHeader = split("\r", $headerTemplate);
429 # - Add header protection
430 push(@headerContentHeader, "\n#ifndef $className" . "_h");
431 push(@headerContentHeader, "\n#define $className" . "_h\n\n");
433 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
434 push(@headerContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
435 return @headerContentHeader;
438 sub GenerateImplementationContentHeader
440 my $interface = shift;
441 my $className = "JS" . $interface->name;
443 my @implContentHeader;
444 if ($interface->extendedAttributes->{"AppleCopyright"}) {
445 @implContentHeader = split("\r", $beginAppleCopyrightForSourceFiles);
447 @implContentHeader = split("\r", $headerTemplate);
450 push(@implContentHeader, "\n#include \"config.h\"\n");
451 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
452 push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
453 push(@implContentHeader, "#include \"$className.h\"\n\n");
454 return @implContentHeader;
457 my %usesToJSNewlyCreated = (
466 sub ShouldGenerateToJSDeclaration
468 my ($hasParent, $interface) = @_;
469 return 0 if ($interface->extendedAttributes->{"SuppressToJSObject"});
470 return 0 if $interface->name eq "AbstractView";
471 return 1 if (!$hasParent or $interface->extendedAttributes->{"JSGenerateToJSObject"} or $interface->extendedAttributes->{"CustomToJSObject"});
475 sub ShouldGenerateToJSImplementation
477 my ($hasParent, $interface) = @_;
478 return 0 if ($interface->extendedAttributes->{"SuppressToJSObject"});
479 return 0 if $interface->name eq "AbstractView";
480 return 1 if ((!$hasParent or $interface->extendedAttributes->{"JSGenerateToJSObject"}) and !$interface->extendedAttributes->{"CustomToJSObject"});
484 sub GetAttributeGetterName
486 my ($interfaceName, $className, $attribute) = @_;
487 if ($attribute->isStatic) {
488 return $codeGenerator->WK_lcfirst($className) . "Constructor" . $codeGenerator->WK_ucfirst($attribute->signature->name);
490 return "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
493 sub GetAttributeSetterName
495 my ($interfaceName, $className, $attribute) = @_;
496 if ($attribute->isStatic) {
497 return "set" . $codeGenerator->WK_ucfirst($className) . "Constructor" . $codeGenerator->WK_ucfirst($attribute->signature->name);
499 return "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
504 my ($className, $function) = @_;
505 my $kind = $function->isStatic ? "Constructor" : "Prototype";
506 return $codeGenerator->WK_lcfirst($className) . $kind . "Function" . $codeGenerator->WK_ucfirst($function->signature->name);
509 sub GetSpecialAccessorFunctionForType
511 my $interface = shift;
513 my $firstParameterType = shift;
514 my $numberOfParameters = shift;
516 foreach my $function (@{$interface->functions}, @{$interface->anonymousFunctions}) {
517 my $specials = $function->signature->specials;
518 my $specialExists = grep { $_ eq $special } @$specials;
519 my $parameters = $function->parameters;
520 if ($specialExists and scalar(@$parameters) == $numberOfParameters and $parameters->[0]->type eq $firstParameterType) {
528 sub HasComplexGetOwnProperty
530 my $interface = shift;
532 my $namedGetterFunction = GetNamedGetterFunction($interface);
533 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
535 my $hasImpureNamedGetter = $namedGetterFunction
536 || $interface->extendedAttributes->{"CustomNamedGetter"};
538 my $hasComplexGetter = $indexedGetterFunction
539 || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}
540 || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"}
541 || $hasImpureNamedGetter;
543 return 1 if $interface->extendedAttributes->{"CheckSecurity"};
544 return 1 if IsDOMGlobalObject($interface);
545 return 1 if $hasComplexGetter;
550 sub InterfaceRequiresAttributesOnInstanceForCompatibility
552 my $interface = shift;
553 my $interfaceName = $interface->name;
555 # Needed for compatibility with existing content
556 return 1 if $interfaceName =~ "Touch";
557 return 1 if $interfaceName =~ "Navigator";
558 # FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=134364 is fixed, we can remove this.
559 return 1 if $interfaceName =~ "XMLHttpRequest";
564 sub InterfaceRequiresAttributesOnInstance
566 my $interface = shift;
567 my $interfaceName = $interface->name;
568 my $namedGetterFunction = GetNamedGetterFunction($interface);
569 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
571 # FIXME: All these return 1 if ... should ideally be removed.
572 # Some of them are unavoidable due to DOM weirdness, in which case we should
573 # add an IDL attribute for them
575 # FIXME: We should rearrange how custom named getters and getOwnPropertySlot
576 # overrides are handled so that we get the correct semantics and lookup ordering
577 my $hasImpureNamedGetter = $namedGetterFunction
578 || $interface->extendedAttributes->{"CustomNamedGetter"};
579 return 1 if $hasImpureNamedGetter
580 || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
582 # FIXME: These two should be fixed by removing the custom override of message, etc
583 return 1 if $interfaceName =~ "Exception";
584 return 1 if $interfaceName =~ "Error";
586 return 1 if IsDOMGlobalObject($interface);
588 return 1 if InterfaceRequiresAttributesOnInstanceForCompatibility($interface);
590 #FIXME: We currently clobber performance for a number of the list types
591 return 1 if $interfaceName =~ "List" && !($interfaceName =~ "Element");
596 sub ConstructorShouldBeOnInstance
598 my $interface = shift;
599 return 1 if $interface->extendedAttributes->{"CheckSecurity"};
600 return HasComplexGetOwnProperty($interface);
603 sub AttributeShouldBeOnInstanceForCompatibility
605 my $interface = shift;
606 my $attribute = shift;
607 my $interfaceName = $interface->name;
611 sub AttributeShouldBeOnInstance
613 my $interface = shift;
614 my $attribute = shift;
616 return 1 if InterfaceRequiresAttributesOnInstance($interface);
617 return 1 if $attribute->signature->type =~ /Constructor$/;
618 return 1 if HasCustomGetter($attribute->signature->extendedAttributes);
619 return 1 if HasCustomSetter($attribute->signature->extendedAttributes);
621 # FIXME: Length is a tricky attribute to handle correctly as it is frequently tied to
622 # objects which also have magic named attributes that can end up being named "length"
623 # and so interfere with lookup ordering. I'm not sure what the correct solution is
625 return 1 if ($attribute->signature->name eq "length") && $interface->name ne "CharacterData";
627 # It becomes hard to reason about attributes that require security checks if we push
628 # them down the prototype chain, so before we do these we'll need to carefully consider
629 # the possible pitfalls.
630 return 1 if $attribute->signature->extendedAttributes->{"CheckSecurityForNode"};
632 return 1 if AttributeShouldBeOnInstanceForCompatibility($interface, $attribute);
634 if ($interface->extendedAttributes->{"CheckSecurity"}) {
635 if ($attribute->signature->extendedAttributes->{"DoNotCheckSecurity"} or
636 $attribute->signature->extendedAttributes->{"DoNotCheckSecurityOnGetter"}) {
644 sub GetIndexedGetterFunction
646 my $interface = shift;
647 return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned long", 1);
650 sub GetNamedGetterFunction
652 my $interface = shift;
653 return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1);
656 sub InstanceAttributeCount
658 my $interface = shift;
660 foreach my $attribute (@{$interface->attributes}) {
661 $count = $count + AttributeShouldBeOnInstance($interface, $attribute);
663 $count = $count + 1 if ConstructorShouldBeOnInstance($interface);
667 sub PrototypeAttributeCount
669 my $interface = shift;
671 foreach my $attribute (@{$interface->attributes}) {
672 $count = $count + 1 if !AttributeShouldBeOnInstance($interface, $attribute);
674 $count = $count + 1 if !ConstructorShouldBeOnInstance($interface);
678 sub InstanceOverridesGetOwnPropertySlot
680 my $interface = shift;
681 my $numInstanceAttributes = InstanceAttributeCount($interface);
683 my $namedGetterFunction = GetNamedGetterFunction($interface);
684 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
686 my $hasImpureNamedGetter = $namedGetterFunction
687 || $interface->extendedAttributes->{"CustomNamedGetter"};
689 my $hasComplexGetter = $indexedGetterFunction
690 || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}
691 || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"}
692 || $hasImpureNamedGetter;
694 return $numInstanceAttributes > 0 || $hasComplexGetter;
698 sub PrototypeOverridesGetOwnPropertySlot
700 my $interface = shift;
701 my $numPrototypeAttributes = PrototypeAttributeCount($interface);
702 my $numConstants = @{$interface->constants};
703 my $numFunctions = @{$interface->functions};
704 return $numFunctions > 0 || $numConstants > 0 || $numPrototypeAttributes > 0;
707 sub InstanceOverridesPutImplementation
709 my $interface = shift;
710 return $interface->extendedAttributes->{"CustomNamedSetter"}
711 || $interface->extendedAttributes->{"CustomIndexedSetter"};
714 sub InstanceOverridesPutDeclaration
716 my $interface = shift;
717 return $interface->extendedAttributes->{"CustomPutFunction"}
718 || $interface->extendedAttributes->{"CustomNamedSetter"}
719 || $interface->extendedAttributes->{"CustomIndexedSetter"};
722 sub InstanceNeedsVisitChildren
724 my $interface = shift;
725 return $interface->extendedAttributes->{"JSCustomMarkFunction"}
726 || $interface->extendedAttributes->{"EventTarget"}
727 || $interface->name eq "EventTarget"
728 || $interface->extendedAttributes->{"ReportExtraMemoryCost"};
735 return "DOMWindow" if $name eq "AbstractView";
742 my $interface = shift;
744 my $interfaceName = $interface->name;
745 my $className = "JS$interfaceName";
746 my %structureFlags = ();
748 my $hasLegacyParent = $interface->extendedAttributes->{"JSLegacyParent"};
749 my $hasRealParent = $interface->parent;
750 my $hasParent = $hasLegacyParent || $hasRealParent;
751 my $parentClassName = GetParentClassName($interface);
752 my $needsVisitChildren = InstanceNeedsVisitChildren($interface);
754 # - Add default header template and header protection
755 push(@headerContentHeader, GenerateHeaderContentHeader($interface));
758 $headerIncludes{"$parentClassName.h"} = 1;
760 $headerIncludes{"JSDOMWrapper.h"} = 1;
761 if ($interface->isException) {
762 $headerIncludes{"<runtime/ErrorPrototype.h>"} = 1;
766 if ($interface->extendedAttributes->{"CustomCall"}) {
767 $headerIncludes{"<runtime/CallData.h>"} = 1;
770 if ($hasParent && $interface->extendedAttributes->{"JSGenerateToNativeObject"}) {
771 $headerIncludes{"$interfaceName.h"} = 1;
774 $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;
776 my $implType = GetImplClassName($interfaceName);
777 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);
778 $implType = $svgNativeType if $svgNativeType;
780 my $svgPropertyOrListPropertyType;
781 $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;
782 $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;
784 my $numConstants = @{$interface->constants};
785 my $numAttributes = @{$interface->attributes};
786 my $numFunctions = @{$interface->functions};
788 push(@headerContent, "\nnamespace WebCore {\n\n");
790 if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
791 $headerIncludes{"$interfaceName.h"} = 1;
793 # Implementation class forward declaration
794 if (IsDOMGlobalObject($interface)) {
795 AddClassForwardIfNeeded($interfaceName) unless $svgPropertyOrListPropertyType;
799 AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
800 AddClassForwardIfNeeded("JSDictionary") if $codeGenerator->IsConstructorTemplate($interface, "Event");
803 push(@headerContent, "class $className : public $parentClassName {\n");
805 # Static create methods
806 push(@headerContent, "public:\n");
807 push(@headerContent, " typedef $parentClassName Base;\n");
808 if ($interfaceName eq "DOMWindow") {
809 push(@headerContent, " static $className* create(JSC::VM& vm, JSC::Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* windowShell)\n");
810 push(@headerContent, " {\n");
811 push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, impl, windowShell);\n");
812 push(@headerContent, " ptr->finishCreation(vm, windowShell);\n");
813 push(@headerContent, " vm.heap.addFinalizer(ptr, destroy);\n");
814 push(@headerContent, " return ptr;\n");
815 push(@headerContent, " }\n\n");
816 } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) {
817 push(@headerContent, " static $className* create(JSC::VM& vm, JSC::Structure* structure, PassRefPtr<$implType> impl)\n");
818 push(@headerContent, " {\n");
819 push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, impl);\n");
820 push(@headerContent, " ptr->finishCreation(vm);\n");
821 push(@headerContent, " vm.heap.addFinalizer(ptr, destroy);\n");
822 push(@headerContent, " return ptr;\n");
823 push(@headerContent, " }\n\n");
824 } elsif ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) {
825 AddIncludesForTypeInHeader($implType) unless $svgPropertyOrListPropertyType;
826 push(@headerContent, " static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
827 push(@headerContent, " {\n");
828 push(@headerContent, " globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(\"Allocated masquerading object\");\n");
829 push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, globalObject, impl);\n");
830 push(@headerContent, " ptr->finishCreation(globalObject->vm());\n");
831 push(@headerContent, " return ptr;\n");
832 push(@headerContent, " }\n\n");
834 AddIncludesForTypeInHeader($implType) unless $svgPropertyOrListPropertyType;
835 push(@headerContent, " static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
836 push(@headerContent, " {\n");
837 push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, globalObject, impl);\n");
838 push(@headerContent, " ptr->finishCreation(globalObject->vm());\n");
839 push(@headerContent, " return ptr;\n");
840 push(@headerContent, " }\n\n");
843 if (IsDOMGlobalObject($interface)) {
844 push(@headerContent, " static const bool needsDestruction = false;\n\n");
848 unless (IsDOMGlobalObject($interface)) {
849 push(@headerContent, " static JSC::JSObject* createPrototype(JSC::VM&, JSC::JSGlobalObject*);\n");
850 push(@headerContent, " static JSC::JSObject* getPrototype(JSC::VM&, JSC::JSGlobalObject*);\n");
853 # JSValue to implementation type
854 if (!$hasParent || $interface->extendedAttributes->{"JSGenerateToNativeObject"}) {
855 if ($interfaceName eq "NodeFilter") {
856 push(@headerContent, " static PassRefPtr<NodeFilter> toWrapped(JSC::VM&, JSC::JSValue);\n");
857 } elsif ($interfaceName eq "DOMStringList") {
858 push(@headerContent, " static PassRefPtr<DOMStringList> toWrapped(JSC::ExecState*, JSC::JSValue);\n");
860 push(@headerContent, " static $implType* toWrapped(JSC::JSValue);\n");
864 $headerTrailingIncludes{"${className}Custom.h"} = 1 if $interface->extendedAttributes->{"JSCustomHeader"};
866 my $namedGetterFunction = GetNamedGetterFunction($interface);
867 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
869 my $hasImpureNamedGetter = $namedGetterFunction
870 || $interface->extendedAttributes->{"CustomNamedGetter"};
872 my $hasComplexGetter =
873 $indexedGetterFunction
874 || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}
875 || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"}
876 || $hasImpureNamedGetter;
878 my $hasGetter = InstanceOverridesGetOwnPropertySlot($interface);
880 if ($hasImpureNamedGetter) {
881 $structureFlags{"JSC::HasImpureGetOwnPropertySlot"} = 1;
883 if ($interface->extendedAttributes->{"NewImpurePropertyFiresWatchpoints"}) {
884 $structureFlags{"JSC::NewImpurePropertyFiresWatchpoints"} = 1;
889 push(@headerContent, " static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n");
890 push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n") if $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"};
891 $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1;
893 if ($hasComplexGetter) {
894 push(@headerContent, " static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n");
895 $structureFlags{"JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero"} = 1;
899 my $overridesPut = InstanceOverridesPutDeclaration($interface);
903 push(@headerContent, " static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n");
904 push(@headerContent, " static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool shouldThrow);\n");
905 push(@headerContent, " bool putDelegate(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n") if $interface->extendedAttributes->{"CustomNamedSetter"};
909 push(@headerContent, " static void destroy(JSC::JSCell*);\n");
910 push(@headerContent, " ~${className}();\n");
914 if ($interfaceName eq "Node") {
915 push(@headerContent, "\n");
916 push(@headerContent, "protected:\n");
917 push(@headerContent, " static WEBKIT_EXPORTDATA const JSC::ClassInfo s_info;\n");
918 push(@headerContent, "public:\n");
919 push(@headerContent, " static const JSC::ClassInfo* info() { return &s_info; }\n\n");
921 push(@headerContent, "\n");
922 push(@headerContent, " DECLARE_INFO;\n\n");
925 if ($interfaceName eq "DOMWindow") {
926 $structureFlags{"JSC::ImplementsHasInstance"} = 1;
928 push(@headerContent, " static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n");
929 push(@headerContent, " {\n");
930 if (IsDOMGlobalObject($interface)) {
931 push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), info());\n");
932 } elsif ($codeGenerator->InheritsInterface($interface, "Element")) {
933 push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSElementType), StructureFlags), info());\n");
934 } elsif ($codeGenerator->InheritsInterface($interface, "Node")) {
935 push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSNodeType), StructureFlags), info());\n");
937 push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n");
939 push(@headerContent, " }\n\n");
941 # Custom pushEventHandlerScope function
942 push(@headerContent, " JSC::JSScope* pushEventHandlerScope(JSC::ExecState*, JSC::JSScope*) const;\n\n") if $interface->extendedAttributes->{"JSCustomPushEventHandlerScope"};
944 # Custom call functions
945 push(@headerContent, " static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);\n\n") if $interface->extendedAttributes->{"CustomCall"};
947 # Custom deleteProperty function
948 push(@headerContent, " static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);\n") if $interface->extendedAttributes->{"CustomDeleteProperty"};
949 push(@headerContent, " static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);\n") if $interface->extendedAttributes->{"CustomDeleteProperty"};
951 # Custom getPropertyNames function exists on DOMWindow
952 if ($interfaceName eq "DOMWindow") {
953 push(@headerContent, " static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
954 push(@headerContent, " static void getGenericPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
955 push(@headerContent, " static void getStructurePropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
956 push(@headerContent, " static uint32_t getEnumerableLength(JSC::ExecState*, JSC::JSObject*);\n");
957 $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;
960 # Custom getOwnPropertyNames function
961 if ($interface->extendedAttributes->{"CustomEnumerateProperty"} || $indexedGetterFunction) {
962 push(@headerContent, " static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
963 $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;
966 # Custom defineOwnProperty function
967 push(@headerContent, " static bool defineOwnProperty(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, const JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interface->extendedAttributes->{"JSCustomDefineOwnProperty"};
969 # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.
970 if ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) {
971 $structureFlags{"JSC::MasqueradesAsUndefined"} = 1;
974 # Constructor object getter
975 unless ($interface->extendedAttributes->{"NoInterfaceObject"}) {
976 push(@headerContent, " static JSC::JSValue getConstructor(JSC::VM&, JSC::JSGlobalObject*);\n");
977 push(@headerContent, " static JSC::JSValue getNamedConstructor(JSC::VM&, JSC::JSGlobalObject*);\n") if $interface->extendedAttributes->{"NamedConstructor"};
980 my $numCustomFunctions = 0;
981 my $numCustomAttributes = 0;
983 my $hasForwardDeclaringFunctions = 0;
984 my $hasForwardDeclaringAttributes = 0;
986 # Attribute and function enums
987 if ($numAttributes > 0) {
988 foreach (@{$interface->attributes}) {
990 $numCustomAttributes++ if HasCustomGetter($attribute->signature->extendedAttributes);
991 $numCustomAttributes++ if HasCustomSetter($attribute->signature->extendedAttributes);
992 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
993 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
994 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
995 push(@headerContent, " JSC::WriteBarrier<JSC::Unknown> m_" . $attribute->signature->name . ";\n");
996 $numCachedAttributes++;
997 $needsVisitChildren = 1;
998 push(@headerContent, "#endif\n") if $conditionalString;
1001 if ($attribute->signature->extendedAttributes->{"ForwardDeclareInHeader"}) {
1002 $hasForwardDeclaringAttributes = 1;
1008 if ($needsVisitChildren) {
1009 push(@headerContent, " static void visitChildren(JSCell*, JSC::SlotVisitor&);\n");
1010 push(@headerContent, " void visitAdditionalChildren(JSC::SlotVisitor&);\n") if $interface->extendedAttributes->{"JSCustomMarkFunction"};
1011 push(@headerContent, "\n");
1014 if ($numCustomAttributes > 0) {
1015 push(@headerContent, "\n // Custom attributes\n");
1017 foreach my $attribute (@{$interface->attributes}) {
1018 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1019 if (HasCustomGetter($attribute->signature->extendedAttributes)) {
1020 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
1021 my $methodName = $codeGenerator->WK_lcfirst($attribute->signature->name);
1022 push(@headerContent, " JSC::JSValue " . $methodName . "(JSC::ExecState*) const;\n");
1023 push(@headerContent, "#endif\n") if $conditionalString;
1025 if (HasCustomSetter($attribute->signature->extendedAttributes) && !IsReadonly($attribute)) {
1026 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
1027 push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n");
1028 push(@headerContent, "#endif\n") if $conditionalString;
1033 foreach my $function (@{$interface->functions}) {
1034 $numCustomFunctions++ if HasCustomMethod($function->signature->extendedAttributes);
1036 if ($function->signature->extendedAttributes->{"ForwardDeclareInHeader"}) {
1037 $hasForwardDeclaringFunctions = 1;
1041 if ($numCustomFunctions > 0) {
1042 my $inAppleCopyright = 0;
1043 push(@headerContent, "\n // Custom functions\n");
1044 foreach my $function (@{$interface->functions}) {
1046 my $needsAppleCopyright = $function->signature->extendedAttributes->{"AppleCopyright"};
1047 if ($needsAppleCopyright) {
1048 if (!$inAppleCopyright) {
1049 push(@headerContent, $beginAppleCopyrightForHeaderFiles);
1050 $inAppleCopyright = 1;
1052 } elsif ($inAppleCopyright) {
1053 push(@headerContent, $endAppleCopyright);
1054 $inAppleCopyright = 0;
1057 next unless HasCustomMethod($function->signature->extendedAttributes);
1058 next if $function->{overloads} && $function->{overloadIndex} != 1;
1059 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1060 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
1061 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $codeGenerator->WK_lcfirst($function->signature->name);
1062 push(@headerContent, " " . ($function->isStatic ? "static " : "") . "JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*);\n");
1063 push(@headerContent, "#endif\n") if $conditionalString;
1065 push(@headerContent, $endAppleCopyright) if $inAppleCopyright;
1069 push(@headerContent, " $implType& impl() const { return *m_impl; }\n");
1070 push(@headerContent, " void releaseImpl() { m_impl->deref(); m_impl = 0; }\n\n");
1071 push(@headerContent, " void releaseImplIfNotNull()\n");
1072 push(@headerContent, " {\n");
1073 push(@headerContent, " if (m_impl) {\n");
1074 push(@headerContent, " m_impl->deref();\n");
1075 push(@headerContent, " m_impl = 0;\n");
1076 push(@headerContent, " }\n");
1077 push(@headerContent, " }\n\n");
1078 push(@headerContent, "private:\n");
1079 push(@headerContent, " $implType* m_impl;\n");
1081 push(@headerContent, " $interfaceName& impl() const\n");
1082 push(@headerContent, " {\n");
1083 push(@headerContent, " return static_cast<$interfaceName&>(Base::impl());\n");
1084 push(@headerContent, " }\n");
1087 push(@headerContent, "protected:\n");
1090 if ($interfaceName eq "DOMWindow") {
1091 push(@headerContent, " $className(JSC::VM&, JSC::Structure*, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
1092 } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) {
1093 push(@headerContent, " $className(JSC::VM&, JSC::Structure*, PassRefPtr<$implType>);\n");
1095 push(@headerContent, " $className(JSC::Structure*, JSDOMGlobalObject*, PassRefPtr<$implType>);\n\n");
1096 push(@headerContent, " void finishCreation(JSC::VM& vm)\n");
1097 push(@headerContent, " {\n");
1098 push(@headerContent, " Base::finishCreation(vm);\n");
1099 push(@headerContent, " ASSERT(inherits(info()));\n");
1100 push(@headerContent, " }\n\n");
1104 if (%structureFlags) {
1105 push(@headerContent, " static const unsigned StructureFlags = ");
1106 foreach my $structureFlag (sort (keys %structureFlags)) {
1107 push(@headerContent, $structureFlag . " | ");
1109 push(@headerContent, "Base::StructureFlags;\n");
1113 if ($interface->extendedAttributes->{"CustomIndexedSetter"}) {
1114 push(@headerContent, " void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n");
1117 if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) {
1118 push(@headerContent, "private:\n");
1119 push(@headerContent, " static bool canGetItemsForName(JSC::ExecState*, $interfaceName*, JSC::PropertyName);\n");
1120 push(@headerContent, " static JSC::EncodedJSValue nameGetter(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::PropertyName);\n");
1123 push(@headerContent, "};\n\n");
1126 GetGenerateIsReachable($interface) ||
1127 GetCustomIsReachable($interface) ||
1128 $interface->extendedAttributes->{"JSCustomFinalize"} ||
1129 $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
1130 if ($interfaceName ne "Node" && $codeGenerator->InheritsInterface($interface, "Node")) {
1131 $headerIncludes{"JSNode.h"} = 1;
1132 push(@headerContent, "class JS${interfaceName}Owner : public JSNodeOwner {\n");
1134 push(@headerContent, "class JS${interfaceName}Owner : public JSC::WeakHandleOwner {\n");
1136 push(@headerContent, "public:\n");
1137 push(@headerContent, " virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);\n");
1138 push(@headerContent, " virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);\n");
1139 push(@headerContent, "};\n");
1140 push(@headerContent, "\n");
1141 push(@headerContent, "inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, $implType*)\n");
1142 push(@headerContent, "{\n");
1143 push(@headerContent, " DEPRECATED_DEFINE_STATIC_LOCAL(JS${interfaceName}Owner, js${interfaceName}Owner, ());\n");
1144 push(@headerContent, " return &js${interfaceName}Owner;\n");
1145 push(@headerContent, "}\n");
1146 push(@headerContent, "\n");
1148 if (ShouldGenerateToJSDeclaration($hasParent, $interface)) {
1149 push(@headerContent, "WEBCORE_EXPORT JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");
1150 push(@headerContent, "inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType& impl) { return toJS(exec, globalObject, &impl); }\n");
1152 if ($usesToJSNewlyCreated{$interfaceName}) {
1153 push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n");
1156 push(@headerContent, "\n");
1158 # Add prototype declaration.
1159 if (HeaderNeedsPrototypeDeclaration($interface)) {
1160 GeneratePrototypeDeclaration(\@headerContent, $className, $interface, $interfaceName);
1163 if ($hasForwardDeclaringFunctions) {
1164 my $inAppleCopyright = 0;
1165 push(@headerContent,"// Functions\n\n");
1166 foreach my $function (@{$interface->functions}) {
1167 next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1168 next unless $function->signature->extendedAttributes->{"ForwardDeclareInHeader"};
1170 my $needsAppleCopyright = $function->signature->extendedAttributes->{"AppleCopyright"};
1171 if ($needsAppleCopyright) {
1172 if (!$inAppleCopyright) {
1173 push(@headerContent, $beginAppleCopyrightForHeaderFiles);
1174 $inAppleCopyright = 1;
1176 } elsif ($inAppleCopyright) {
1177 push(@headerContent, $endAppleCopyright);
1178 $inAppleCopyright = 0;
1181 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1182 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
1183 my $functionName = GetFunctionName($className, $function);
1184 push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n");
1185 push(@headerContent, "#endif\n") if $conditionalString;
1188 push(@headerContent, $endAppleCopyright) if $inAppleCopyright;
1191 if ($hasForwardDeclaringAttributes) {
1192 push(@headerContent,"// Attributes\n\n");
1193 foreach my $attribute (@{$interface->attributes}) {
1194 next unless $attribute->signature->extendedAttributes->{"ForwardDeclareInHeader"};
1196 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1197 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
1198 my $getter = GetAttributeGetterName($interfaceName, $className, $attribute);
1199 push(@headerContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::PropertyName);\n");
1200 if (!IsReadonly($attribute)) {
1201 my $setter = GetAttributeSetterName($interfaceName, $className, $attribute);
1202 push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::EncodedJSValue);\n");
1204 push(@headerContent, "#endif\n") if $conditionalString;
1208 if (HasCustomConstructor($interface)) {
1209 push(@headerContent, "// Custom constructor\n");
1210 push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL construct${className}(JSC::ExecState*);\n\n");
1213 if ($codeGenerator->IsConstructorTemplate($interface, "Event")) {
1214 push(@headerContent, "bool fill${interfaceName}Init(${interfaceName}Init&, JSDictionary&);\n\n");
1217 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
1218 push(@headerContent, "\n} // namespace WebCore\n\n");
1219 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
1220 push(@headerContent, "#endif\n");
1222 if ($interface->extendedAttributes->{"AppleCopyright"}) {
1223 push(@headerContent, split("\r", $endAppleCopyright));
1227 sub GenerateAttributesHashTable
1229 my ($object, $interface, $isInstance, $hashKeys, $hashSpecials, $hashValue1, $hashValue2, $conditionals, $entries) = @_;
1231 # FIXME: These should be functions on $interface.
1232 my $interfaceName = $interface->name;
1233 my $className = "JS$interfaceName";
1235 # - Add all attributes in a hashtable definition
1236 my $numAttributes = 0;
1238 $numAttributes = InstanceAttributeCount($interface);
1240 $numAttributes = PrototypeAttributeCount($interface);
1244 if (ConstructorShouldBeOnInstance($interface) == $isInstance) {
1246 if (!$interface->extendedAttributes->{"NoInterfaceObject"}) {
1247 die if !$numAttributes;
1248 push(@$hashKeys, "constructor");
1249 my $getter = "js" . $interfaceName . "Constructor";
1250 push(@$hashValue1, $getter);
1251 if ($interface->extendedAttributes->{"ReplaceableConstructor"}) {
1252 my $setter = "setJS" . $interfaceName . "Constructor";
1253 push(@$hashValue2, $setter);
1254 push(@$hashSpecials, "DontEnum | DontDelete");
1256 push(@$hashValue2, "0");
1257 push(@$hashSpecials, "DontEnum | ReadOnly");
1262 return 0 if !$numAttributes;
1264 foreach my $attribute (@{$interface->attributes}) {
1265 next if ($attribute->isStatic);
1266 next if AttributeShouldBeOnInstance($interface, $attribute) != $isInstance;
1267 my $name = $attribute->signature->name;
1268 push(@$hashKeys, $name);
1271 # As per Web IDL specification, constructor properties on the ECMAScript global object should be
1272 # configurable and should not be enumerable.
1273 my $is_global_constructor = $attribute->signature->type =~ /Constructor$/;
1274 push(@specials, "DontDelete") unless ($attribute->signature->extendedAttributes->{"Deletable"} || $is_global_constructor);
1275 push(@specials, "DontEnum") if ($attribute->signature->extendedAttributes->{"NotEnumerable"} || $is_global_constructor);
1276 push(@specials, "ReadOnly") if IsReadonly($attribute);
1277 push(@specials, "CustomAccessor") unless $is_global_constructor;
1278 my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1279 push(@$hashSpecials, $special);
1281 my $getter = GetAttributeGetterName($interfaceName, $className, $attribute);
1282 push(@$hashValue1, $getter);
1284 if (IsReadonly($attribute)) {
1285 push(@$hashValue2, "0");
1287 my $setter = GetAttributeSetterName($interfaceName, $className, $attribute);
1288 push(@$hashValue2, $setter);
1291 my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
1293 $conditionals->{$name} = $conditional;
1297 return $numAttributes;
1300 sub GenerateParametersCheckExpression
1302 my $numParameters = shift;
1303 my $function = shift;
1305 my @andExpression = ();
1306 push(@andExpression, "argsCount == $numParameters");
1307 my $parameterIndex = 0;
1308 my %usedArguments = ();
1309 foreach my $parameter (@{$function->parameters}) {
1310 last if $parameterIndex >= $numParameters;
1311 my $value = "arg$parameterIndex";
1312 my $type = $parameter->type;
1314 # Only DOMString or wrapper types are checked.
1315 # For DOMString with StrictTypeChecking only Null, Undefined and Object
1316 # are accepted for compatibility. Otherwise, no restrictions are made to
1317 # match the non-overloaded behavior.
1318 # FIXME: Implement WebIDL overload resolution algorithm.
1319 if ($codeGenerator->IsStringType($type) || $codeGenerator->IsEnumType($type)) {
1320 if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
1321 push(@andExpression, "(${value}.isUndefinedOrNull() || ${value}.isString() || ${value}.isObject())");
1322 $usedArguments{$parameterIndex} = 1;
1324 } elsif ($codeGenerator->IsCallbackInterface($parameter->type)) {
1325 # For Callbacks only checks if the value is null or object.
1326 push(@andExpression, "(${value}.isNull() || ${value}.isFunction())");
1327 $usedArguments{$parameterIndex} = 1;
1328 } elsif ($codeGenerator->GetArrayType($type) || $codeGenerator->GetSequenceType($type)) {
1329 # FIXME: Add proper support for T[], T[]?, sequence<T>
1330 if ($parameter->isNullable) {
1331 push(@andExpression, "(${value}.isNull() || (${value}.isObject() && isJSArray(${value})))");
1333 push(@andExpression, "(${value}.isObject() && isJSArray(${value}))");
1335 $usedArguments{$parameterIndex} = 1;
1336 } elsif (!IsNativeType($type)) {
1337 if ($parameter->isNullable) {
1338 push(@andExpression, "(${value}.isNull() || (${value}.isObject() && asObject(${value})->inherits(JS${type}::info())))");
1340 push(@andExpression, "(${value}.isObject() && asObject(${value})->inherits(JS${type}::info()))");
1342 $usedArguments{$parameterIndex} = 1;
1346 my $res = join(" && ", @andExpression);
1347 $res = "($res)" if @andExpression > 1;
1348 return ($res, sort {$a <=> $b} (keys %usedArguments));
1351 # As per Web IDL specification, the length of a function Object is
1352 # its number of mandatory parameters.
1353 sub GetFunctionLength
1355 my $function = shift;
1357 my $numMandatoryParams = 0;
1358 foreach my $parameter (@{$function->parameters}) {
1359 # Abort as soon as we find the first optional parameter as no mandatory
1360 # parameter can follow an optional one.
1361 last if $parameter->isOptional;
1362 $numMandatoryParams++;
1364 return $numMandatoryParams;
1367 sub GenerateFunctionParametersCheck
1369 my $function = shift;
1371 my @orExpression = ();
1372 my $numParameters = 0;
1373 my @neededArguments = ();
1374 my $hasVariadic = 0;
1375 my $numMandatoryParams = @{$function->parameters};
1377 foreach my $parameter (@{$function->parameters}) {
1378 if ($parameter->isOptional) {
1379 my ($expression, @usedArguments) = GenerateParametersCheckExpression($numParameters, $function);
1380 push(@orExpression, $expression);
1381 push(@neededArguments, @usedArguments);
1382 $numMandatoryParams--;
1384 if ($parameter->isVariadic) {
1390 if (!$hasVariadic) {
1391 my ($expression, @usedArguments) = GenerateParametersCheckExpression($numParameters, $function);
1392 push(@orExpression, $expression);
1393 push(@neededArguments, @usedArguments);
1395 return ($numMandatoryParams, join(" || ", @orExpression), @neededArguments);
1398 sub GenerateOverloadedFunction
1400 my $function = shift;
1401 my $interface = shift;
1402 my $interfaceName = shift;
1404 # Generate code for choosing the correct overload to call. Overloads are
1405 # chosen based on the total number of arguments passed and the type of
1406 # values passed in non-primitive argument slots. When more than a single
1407 # overload is applicable, precedence is given according to the order of
1408 # declaration in the IDL.
1410 my $kind = $function->isStatic ? "Constructor" : "Prototype";
1411 my $functionName = "js${interfaceName}${kind}Function" . $codeGenerator->WK_ucfirst($function->signature->name);
1413 push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");
1414 push(@implContent, <<END);
1416 size_t argsCount = exec->argumentCount();
1419 my %fetchedArguments = ();
1420 my $leastNumMandatoryParams = 255;
1422 foreach my $overload (@{$function->{overloads}}) {
1423 my ($numMandatoryParams, $parametersCheck, @neededArguments) = GenerateFunctionParametersCheck($overload);
1424 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
1426 foreach my $parameterIndex (@neededArguments) {
1427 next if exists $fetchedArguments{$parameterIndex};
1428 push(@implContent, " JSValue arg$parameterIndex(exec->argument($parameterIndex));\n");
1429 $fetchedArguments{$parameterIndex} = 1;
1432 my $conditionalString = $codeGenerator->GenerateConditionalString($overload->signature);
1433 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1435 push(@implContent, " if ($parametersCheck)\n");
1436 push(@implContent, " return ${functionName}$overload->{overloadIndex}(exec);\n");
1437 push(@implContent, "#endif\n\n") if $conditionalString;
1440 if ($leastNumMandatoryParams >= 1) {
1441 push(@implContent, " if (argsCount < $leastNumMandatoryParams)\n");
1442 push(@implContent, " return throwVMError(exec, createNotEnoughArgumentsError(exec));\n");
1444 push(@implContent, <<END);
1445 return throwVMTypeError(exec);
1451 sub GetNativeTypeForConversions
1453 my $interface = shift;
1454 my $interfaceName = $interface->name;
1455 $interfaceName = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName) if $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName);
1456 return $interfaceName;
1459 # See http://refspecs.linux-foundation.org/cxxabi-1.83.html.
1460 sub GetGnuVTableRefForInterface
1462 my $interface = shift;
1463 my $vtableName = GetGnuVTableNameForInterface($interface);
1467 my $typename = GetNativeTypeForConversions($interface);
1468 my $offset = GetGnuVTableOffsetForType($typename);
1469 return "&" . $vtableName . "[" . $offset . "]";
1472 sub GetGnuVTableNameForInterface
1474 my $interface = shift;
1475 my $typename = GetNativeTypeForConversions($interface);
1476 my $templatePosition = index($typename, "<");
1477 return "" if $templatePosition != -1;
1478 return "" if GetImplementationLacksVTableForInterface($interface);
1479 return "" if GetSkipVTableValidationForInterface($interface);
1480 return "_ZTV" . GetGnuMangledNameForInterface($interface);
1483 sub GetGnuMangledNameForInterface
1485 my $interface = shift;
1486 my $typename = GetNativeTypeForConversions($interface);
1487 my $templatePosition = index($typename, "<");
1488 if ($templatePosition != -1) {
1491 my $mangledType = length($typename) . $typename;
1492 my $namespace = GetNamespaceForInterface($interface);
1493 my $mangledNamespace = "N" . length($namespace) . $namespace;
1494 return $mangledNamespace . $mangledType . "E";
1497 sub GetGnuVTableOffsetForType
1499 my $typename = shift;
1500 if ($typename eq "SVGAElement"
1501 || $typename eq "SVGCircleElement"
1502 || $typename eq "SVGClipPathElement"
1503 || $typename eq "SVGDefsElement"
1504 || $typename eq "SVGEllipseElement"
1505 || $typename eq "SVGForeignObjectElement"
1506 || $typename eq "SVGGElement"
1507 || $typename eq "SVGImageElement"
1508 || $typename eq "SVGLineElement"
1509 || $typename eq "SVGPathElement"
1510 || $typename eq "SVGPolyElement"
1511 || $typename eq "SVGPolygonElement"
1512 || $typename eq "SVGPolylineElement"
1513 || $typename eq "SVGRectElement"
1514 || $typename eq "SVGSVGElement"
1515 || $typename eq "SVGGraphicsElement"
1516 || $typename eq "SVGSwitchElement"
1517 || $typename eq "SVGTextElement"
1518 || $typename eq "SVGUseElement") {
1524 # See http://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B_Name_Mangling.
1525 sub GetWinVTableRefForInterface
1527 my $interface = shift;
1528 my $vtableName = GetWinVTableNameForInterface($interface);
1529 return 0 if !$vtableName;
1530 return "__identifier(\"" . $vtableName . "\")";
1533 sub GetWinVTableNameForInterface
1535 my $interface = shift;
1536 my $typename = GetNativeTypeForConversions($interface);
1537 my $templatePosition = index($typename, "<");
1538 return "" if $templatePosition != -1;
1539 return "" if GetImplementationLacksVTableForInterface($interface);
1540 return "" if GetSkipVTableValidationForInterface($interface);
1541 return "??_7" . GetWinMangledNameForInterface($interface) . "6B@";
1544 sub GetWinMangledNameForInterface
1546 my $interface = shift;
1547 my $typename = GetNativeTypeForConversions($interface);
1548 my $namespace = GetNamespaceForInterface($interface);
1549 return $typename . "@" . $namespace . "@@";
1552 sub GetNamespaceForInterface
1554 my $interface = shift;
1555 return $interface->extendedAttributes->{"ImplementationNamespace"} || "WebCore";
1558 sub GetImplementationLacksVTableForInterface
1560 my $interface = shift;
1561 return $interface->extendedAttributes->{"ImplementationLacksVTable"};
1564 sub GetSkipVTableValidationForInterface
1566 my $interface = shift;
1567 return $interface->extendedAttributes->{"SkipVTableValidation"};
1570 # URL becomes url, but SetURL becomes setURL.
1574 my $ret = lcfirst($param);
1575 $ret =~ s/hTML/html/ if $ret =~ /^hTML/;
1576 $ret =~ s/uRL/url/ if $ret =~ /^uRL/;
1577 $ret =~ s/jS/js/ if $ret =~ /^jS/;
1578 $ret =~ s/xML/xml/ if $ret =~ /^xML/;
1579 $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/;
1580 $ret =~ s/cSS/css/ if $ret =~ /^cSS/;
1582 # For HTML5 FileSystem API Flags attributes.
1583 # (create is widely used to instantiate an object and must be avoided.)
1584 $ret =~ s/^create/isCreate/ if $ret =~ /^create$/;
1585 $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/;
1590 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
1591 sub GetRuntimeEnableFunctionName
1593 my $signature = shift;
1595 # If a parameter is given (e.g. "EnabledAtRuntime=FeatureName") return the RuntimeEnabledFeatures::sharedFeatures().{FeatureName}Enabled() method.
1596 return "RuntimeEnabledFeatures::sharedFeatures()." . ToMethodName($signature->extendedAttributes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"EnabledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "VALUE_IS_MISSING");
1598 # Otherwise return a function named RuntimeEnabledFeatures::sharedFeatures().{methodName}Enabled().
1599 return "RuntimeEnabledFeatures::sharedFeatures()." . ToMethodName($signature->name) . "Enabled";
1602 sub GetCastingHelperForThisObject
1604 my $interface = shift;
1606 if ($interface->name eq "Node") {
1607 return "jsNodeCast";
1609 if ($interface->name eq "Element") {
1610 return "jsElementCast";
1612 return "jsDynamicCast<JS" . $interface->name . "*>";
1615 sub GetCastingHelperForBaseObject
1617 my $interface = shift;
1619 if ($interface->name eq "Node") {
1620 return "jsNodeCast";
1622 if ($interface->name eq "Element") {
1623 return "jsElementCast";
1625 return "jsCast<JS" . $interface->name . "*>";
1628 sub GetIndexedGetterExpression
1630 my $indexedGetterFunction = shift;
1631 if ($indexedGetterFunction->signature->type eq "DOMString") {
1632 return "jsStringOrUndefined(exec, thisObject->impl().item(index))";
1634 return "toJS(exec, thisObject->globalObject(), thisObject->impl().item(index))";
1637 sub GenerateImplementation
1639 my ($object, $interface) = @_;
1641 my $interfaceName = $interface->name;
1642 my $className = "JS$interfaceName";
1644 my $hasLegacyParent = $interface->extendedAttributes->{"JSLegacyParent"};
1645 my $hasRealParent = $interface->parent;
1646 my $hasParent = $hasLegacyParent || $hasRealParent;
1647 my $parentClassName = GetParentClassName($interface);
1648 my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface);
1649 my $eventTarget = $interface->extendedAttributes->{"EventTarget"} || ($codeGenerator->InheritsInterface($interface, "EventTarget") && $interface->name ne "EventTarget");
1650 my $needsVisitChildren = InstanceNeedsVisitChildren($interface);
1652 my $namedGetterFunction = GetNamedGetterFunction($interface);
1653 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
1655 # - Add default header template
1656 push(@implContentHeader, GenerateImplementationContentHeader($interface));
1658 $implIncludes{"JSDOMBinding.h"} = 1;
1659 $implIncludes{"<wtf/GetPtr.h>"} = 1;
1660 $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $indexedGetterFunction;
1662 my $implType = GetImplClassName($interfaceName);
1663 AddIncludesForTypeInImpl($implType);
1667 push(@implContent, "\nusing namespace JSC;\n\n");
1668 push(@implContent, "namespace WebCore {\n\n");
1670 my $numConstants = @{$interface->constants};
1671 my $numFunctions = @{$interface->functions};
1672 my $numAttributes = @{$interface->attributes};
1674 if ($numFunctions > 0) {
1675 my $inAppleCopyright = 0;
1676 push(@implContent,"// Functions\n\n");
1677 foreach my $function (@{$interface->functions}) {
1678 next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1679 next if $function->signature->extendedAttributes->{"ForwardDeclareInHeader"};
1681 my $needsAppleCopyright = $function->signature->extendedAttributes->{"AppleCopyright"};
1682 if ($needsAppleCopyright) {
1683 if (!$inAppleCopyright) {
1684 push(@implContent, $beginAppleCopyrightForHeaderFiles);
1685 $inAppleCopyright = 1;
1687 } elsif ($inAppleCopyright) {
1688 push(@implContent, $endAppleCopyright);
1689 $inAppleCopyright = 0;
1692 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1693 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1694 my $functionName = GetFunctionName($className, $function);
1695 push(@implContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n");
1696 push(@implContent, "#endif\n") if $conditionalString;
1699 push(@implContent, $endAppleCopyright) if $inAppleCopyright;
1701 push(@implContent, "\n");
1704 if ($numAttributes > 0 || !$interface->extendedAttributes->{"NoInterfaceObject"}) {
1705 push(@implContent, "// Attributes\n\n");
1706 foreach my $attribute (@{$interface->attributes}) {
1707 next if $attribute->signature->extendedAttributes->{"ForwardDeclareInHeader"};
1709 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1710 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1711 my $getter = GetAttributeGetterName($interfaceName, $className, $attribute);
1712 push(@implContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::PropertyName);\n");
1713 if (!IsReadonly($attribute)) {
1714 my $setter = GetAttributeSetterName($interfaceName, $className, $attribute);
1715 push(@implContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::EncodedJSValue);\n");
1717 push(@implContent, "#endif\n") if $conditionalString;
1720 if (!$interface->extendedAttributes->{"NoInterfaceObject"}) {
1721 my $getter = "js" . $interfaceName . "Constructor";
1722 push(@implContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::PropertyName);\n");
1725 if ($interface->extendedAttributes->{"ReplaceableConstructor"}) {
1726 my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";
1727 push(@implContent, "void ${constructorFunctionName}(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::EncodedJSValue);\n");
1730 push(@implContent, "\n");
1733 # Add prototype declaration.
1734 if (!HeaderNeedsPrototypeDeclaration($interface)) {
1735 GeneratePrototypeDeclaration(\@implContent, $className, $interface, $interfaceName);
1738 # Add constructor declaration
1739 if (!$interface->extendedAttributes->{"NoInterfaceObject"}) {
1740 $implIncludes{"JSDOMBinding.h"} = 1;
1741 if ($interface->extendedAttributes->{"NamedConstructor"}) {
1742 $implIncludes{"DOMConstructorWithDocument.h"} = 1;
1744 GenerateConstructorDeclaration(\@implContent, $className, $interface, $interfaceName);
1749 my @hashValue1 = ();
1750 my @hashValue2 = ();
1751 my @hashSpecials = ();
1752 my %conditionals = ();
1753 my $hashName = $className . "Table";
1755 my $numInstanceAttributes = GenerateAttributesHashTable($object, $interface, 1,
1756 \@hashKeys, \@hashSpecials,
1757 \@hashValue1, \@hashValue2,
1760 $object->GenerateHashTable($hashName, $numInstanceAttributes,
1761 \@hashKeys, \@hashSpecials,
1762 \@hashValue1, \@hashValue2,
1763 \%conditionals, 0) if $numInstanceAttributes > 0;
1765 # - Add all constants
1766 if (!$interface->extendedAttributes->{"NoInterfaceObject"}) {
1768 my $hashName = $className . "ConstructorTable";
1771 my @hashValue1 = ();
1772 my @hashValue2 = ();
1773 my @hashSpecials = ();
1774 my %conditionals = ();
1776 my $needsConstructorTable = 0;
1778 foreach my $constant (@{$interface->constants}) {
1779 my $name = $constant->name;
1780 push(@hashKeys, $name);
1781 push(@hashValue1, $constant->value);
1782 push(@hashValue2, "0");
1783 push(@hashSpecials, "DontDelete | ReadOnly | ConstantInteger");
1785 my $implementedBy = $constant->extendedAttributes->{"ImplementedBy"};
1786 if ($implementedBy) {
1787 $implIncludes{"${implementedBy}.h"} = 1;
1789 my $conditional = $constant->extendedAttributes->{"Conditional"};
1791 $conditionals{$name} = $conditional;
1797 foreach my $attribute (@{$interface->attributes}) {
1798 next unless ($attribute->isStatic);
1799 my $name = $attribute->signature->name;
1800 push(@hashKeys, $name);
1803 push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};
1804 push(@specials, "ReadOnly") if IsReadonly($attribute);
1805 my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1806 push(@hashSpecials, $special);
1808 my $getter = GetAttributeGetterName($interfaceName, $className, $attribute);
1809 push(@hashValue1, $getter);
1811 if (IsReadonly($attribute)) {
1812 push(@hashValue2, "0");
1814 my $setter = GetAttributeSetterName($interfaceName, $className, $attribute);
1815 push(@hashValue2, $setter);
1818 my $conditional = $attribute->signature->extendedAttributes->{"Conditional"};
1820 $conditionals{$name} = $conditional;
1826 foreach my $function (@{$interface->functions}) {
1827 next unless ($function->isStatic);
1828 next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1829 my $name = $function->signature->name;
1830 push(@hashKeys, $name);
1832 my $functionName = GetFunctionName($className, $function);
1833 push(@hashValue1, $functionName);
1835 my $functionLength = GetFunctionLength($function);
1836 push(@hashValue2, $functionLength);
1839 push(@specials, "DontDelete") if $interface->extendedAttributes->{"OperationsNotDeletable"}
1840 || $function->signature->extendedAttributes->{"NotDeletable"};
1841 push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"NotEnumerable"};
1842 push(@specials, "JSC::Function");
1843 my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1844 push(@hashSpecials, $special);
1846 my $conditional = $function->signature->extendedAttributes->{"Conditional"};
1848 $conditionals{$name} = $conditional;
1854 $object->GenerateHashTable($hashName, $hashSize,
1855 \@hashKeys, \@hashSpecials,
1856 \@hashValue1, \@hashValue2,
1857 \%conditionals, 1) if $hashSize > 0;
1859 push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($interface));
1861 my $protoClassName = "${className}Prototype";
1862 GenerateConstructorDefinitions(\@implContent, $className, $protoClassName, $interfaceName, $visibleInterfaceName, $interface);
1863 if ($interface->extendedAttributes->{"NamedConstructor"}) {
1864 GenerateConstructorDefinitions(\@implContent, $className, $protoClassName, $interfaceName, $interface->extendedAttributes->{"NamedConstructor"}, $interface, "GeneratingNamedConstructor");
1868 # - Add functions and constants to a hashtable definition
1870 $hashName = $className . "PrototypeTable";
1879 my $numPrototypeAttributes = GenerateAttributesHashTable($object, $interface, 0,
1880 \@hashKeys, \@hashSpecials,
1881 \@hashValue1, \@hashValue2,
1883 my $hashSize = $numPrototypeAttributes;
1885 foreach my $constant (@{$interface->constants}) {
1886 my $name = $constant->name;
1888 push(@hashKeys, $name);
1889 push(@hashValue1, $constant->value);
1890 push(@hashValue2, "0");
1891 push(@hashSpecials, "DontDelete | ReadOnly | ConstantInteger");
1893 my $conditional = $constant->extendedAttributes->{"Conditional"};
1895 $conditionals{$name} = $conditional;
1901 my @runtimeEnabledFunctions = ();
1903 foreach my $function (@{$interface->functions}) {
1904 next if ($function->isStatic);
1905 next if $function->{overloadIndex} && $function->{overloadIndex} > 1;
1906 my $name = $function->signature->name;
1907 push(@hashKeys, $name);
1909 my $functionName = GetFunctionName($className, $function);
1910 push(@hashValue1, $functionName);
1912 my $functionLength = GetFunctionLength($function);
1913 push(@hashValue2, $functionLength);
1916 push(@specials, "DontDelete") if $interface->extendedAttributes->{"OperationsNotDeletable"}
1917 || $function->signature->extendedAttributes->{"NotDeletable"};
1918 push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"NotEnumerable"};
1919 push(@specials, "JSC::Function");
1920 my $special = (@specials > 0) ? join(" | ", @specials) : "0";
1921 push(@hashSpecials, $special);
1923 my $conditional = $function->signature->extendedAttributes->{"Conditional"};
1925 $conditionals{$name} = $conditional;
1928 push(@runtimeEnabledFunctions, $function) if $function->signature->extendedAttributes->{"EnabledAtRuntime"};
1933 my $justGenerateValueArray = !IsDOMGlobalObject($interface);
1935 $object->GenerateHashTable($hashName, $hashSize,
1936 \@hashKeys, \@hashSpecials,
1937 \@hashValue1, \@hashValue2,
1938 \%conditionals, $justGenerateValueArray);
1940 if ($justGenerateValueArray) {
1941 push(@implContent, "WEBCORE_EXPORT const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}Prototype\", &Base::s_info, 0, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
1943 push(@implContent, "WEBCORE_EXPORT const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}Prototype\", &Base::s_info, &${className}PrototypeTable, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
1946 if (PrototypeOverridesGetOwnPropertySlot($interface)) {
1947 my $numPrototypeAttributes = PrototypeAttributeCount($interface);
1948 if (IsDOMGlobalObject($interface)) {
1949 push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)\n");
1950 push(@implContent, "{\n");
1951 push(@implContent, " VM& vm = exec->vm();\n");
1952 push(@implContent, " UNUSED_PARAM(vm);\n");
1953 push(@implContent, " ${className}Prototype* thisObject = jsCast<${className}Prototype*>(object);\n");
1955 if ($numConstants eq 0 && $numFunctions eq 0 && $numPrototypeAttributes eq 0) {
1956 push(@implContent, " return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);\n");
1957 } elsif ($numConstants eq 0 && $numPrototypeAttributes eq 0) {
1958 push(@implContent, " return getStaticFunctionSlot<JSObject>(exec, ${className}PrototypeTable, thisObject, propertyName, slot);\n");
1959 } elsif ($numFunctions eq 0 && $numPrototypeAttributes eq 0) {
1960 push(@implContent, " return getStaticValueSlot<${className}Prototype, JSObject>(exec, ${className}PrototypeTable, thisObject, propertyName, slot);\n");
1962 push(@implContent, " return getStaticPropertySlot<${className}Prototype, JSObject>(exec, ${className}PrototypeTable, thisObject, propertyName, slot);\n");
1964 push(@implContent, "}\n\n");
1965 } elsif ($numConstants > 0 || $numFunctions > 0 || $numPrototypeAttributes > 0) {
1966 push(@implContent, "void ${className}Prototype::finishCreation(VM& vm)\n");
1967 push(@implContent, "{\n");
1968 push(@implContent, " Base::finishCreation(vm);\n");
1969 push(@implContent, " reifyStaticProperties(vm, ${className}PrototypeTableValues, *this);\n");
1971 foreach my $function (@runtimeEnabledFunctions) {
1972 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1973 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1974 AddToImplIncludes("RuntimeEnabledFeatures.h");
1975 my $signature = $function->signature;
1976 my $enable_function = GetRuntimeEnableFunctionName($signature);
1977 my $name = $signature->name;
1978 push(@implContent, " if (!${enable_function}()) {\n");
1979 push(@implContent, " Identifier propertyName(&vm, reinterpret_cast<const LChar*>(\"$name\"), strlen(\"$name\"));\n");
1980 push(@implContent, " removeDirect(vm, propertyName);\n");
1981 push(@implContent, " }\n");
1982 push(@implContent, "#endif\n") if $conditionalString;
1984 push(@implContent, "}\n\n");
1986 push(@implContent, "void ${className}Prototype::finishCreation(VM& vm)\n");
1987 push(@implContent, "{\n");
1988 push(@implContent, " Base::finishCreation(vm);\n");
1989 push(@implContent, "}\n\n");
1993 if ($interface->extendedAttributes->{"JSCustomNamedGetterOnPrototype"}) {
1994 push(@implContent, "void ${className}Prototype::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\n");
1995 push(@implContent, "{\n");
1996 push(@implContent, " ${className}Prototype* thisObject = jsCast<${className}Prototype*>(cell);\n");
1997 push(@implContent, " if (thisObject->putDelegate(exec, propertyName, value, slot))\n");
1998 push(@implContent, " return;\n");
1999 push(@implContent, " Base::put(thisObject, exec, propertyName, value, slot);\n");
2000 push(@implContent, "}\n\n");
2003 # - Initialize static ClassInfo object
2004 push(@implContent, "WEBCORE_EXPORT const ClassInfo $className" . "::s_info = { \"${visibleInterfaceName}\", &Base::s_info, ");
2006 if ($numInstanceAttributes > 0) {
2007 push(@implContent, "&${className}Table");
2009 push(@implContent, "0");
2011 push(@implContent, ", CREATE_METHOD_TABLE($className) };\n\n");
2013 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType);
2014 $implType = $svgNativeType if $svgNativeType;
2016 my $svgPropertyOrListPropertyType;
2017 $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType;
2018 $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType;
2021 if ($interfaceName eq "DOMWindow") {
2022 AddIncludesForTypeInImpl("JSDOMWindowShell");
2023 push(@implContent, "${className}::$className(VM& vm, Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
2024 push(@implContent, " : $parentClassName(vm, structure, impl, shell)\n");
2025 push(@implContent, "{\n");
2026 push(@implContent, "}\n\n");
2027 } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) {
2028 AddIncludesForTypeInImpl($interfaceName);
2029 push(@implContent, "${className}::$className(VM& vm, Structure* structure, PassRefPtr<$implType> impl)\n");
2030 push(@implContent, " : $parentClassName(vm, structure, impl)\n");
2031 push(@implContent, "{\n");
2032 push(@implContent, "}\n\n");
2034 push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
2036 push(@implContent, " : $parentClassName(structure, globalObject, impl)\n");
2038 push(@implContent, " : $parentClassName(structure, globalObject)\n");
2039 push(@implContent, " , m_impl(impl.leakRef())\n");
2041 push(@implContent, "{\n");
2042 push(@implContent, "}\n\n");
2045 unless (IsDOMGlobalObject($interface)) {
2046 push(@implContent, "JSObject* ${className}::createPrototype(VM& vm, JSGlobalObject* globalObject)\n");
2047 push(@implContent, "{\n");
2048 if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
2049 push(@implContent, " return ${className}Prototype::create(vm, globalObject, ${className}Prototype::createStructure(vm, globalObject, ${parentClassName}::getPrototype(vm, globalObject)));\n");
2051 my $prototype = $interface->isException ? "errorPrototype" : "objectPrototype";
2052 push(@implContent, " return ${className}Prototype::create(vm, globalObject, ${className}Prototype::createStructure(vm, globalObject, globalObject->${prototype}()));\n");
2054 push(@implContent, "}\n\n");
2056 push(@implContent, "JSObject* ${className}::getPrototype(VM& vm, JSGlobalObject* globalObject)\n");
2057 push(@implContent, "{\n");
2058 push(@implContent, " return getDOMPrototype<${className}>(vm, globalObject);\n");
2059 push(@implContent, "}\n\n");
2063 # FIXME: This destroy function should not be necessary, as
2064 # a finalizer should be called for each DOM object wrapper.
2065 # However, that seems not to be the case, so this has been
2066 # added back to avoid leaking while we figure out why the
2067 # finalizers are not always getting called. The work tracking
2068 # the finalizer issue is being tracked in http://webkit.org/b/75451
2069 push(@implContent, "void ${className}::destroy(JSC::JSCell* cell)\n");
2070 push(@implContent, "{\n");
2071 push(@implContent, " ${className}* thisObject = static_cast<${className}*>(cell);\n");
2072 push(@implContent, " thisObject->${className}::~${className}();\n");
2073 push(@implContent, "}\n\n");
2075 # We also need a destructor for the allocateCell to work properly with the destructor-free part of the heap.
2076 # Otherwise, these destroy functions/destructors won't get called.
2077 push(@implContent, "${className}::~${className}()\n");
2078 push(@implContent, "{\n");
2079 push(@implContent, " releaseImplIfNotNull();\n");
2080 push(@implContent, "}\n\n");
2083 my $hasGetter = InstanceOverridesGetOwnPropertySlot($interface);
2087 if (!$interface->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
2088 push(@implContent, "bool ${className}::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)\n");
2089 push(@implContent, "{\n");
2090 push(@implContent, " ${className}* thisObject = jsCast<${className}*>(object);\n");
2091 push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n");
2092 push(@implContent, GenerateGetOwnPropertySlotBody($interface, $interfaceName, $className, $numInstanceAttributes > 0, 0));
2093 push(@implContent, "}\n\n");
2096 if ($indexedGetterFunction || $namedGetterFunction
2097 || $interface->extendedAttributes->{"CustomNamedGetter"}
2098 || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) {
2099 push(@implContent, "bool ${className}::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)\n");
2100 push(@implContent, "{\n");
2101 push(@implContent, " ${className}* thisObject = jsCast<${className}*>(object);\n");
2102 push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n");
2104 # Sink the int-to-string conversion that happens when we create a PropertyName
2105 # to the point where we actually need it.
2106 my $generatedPropertyName = 0;
2107 my $propertyNameGeneration = sub {
2108 if ($generatedPropertyName) {
2111 push(@implContent, " PropertyName propertyName = Identifier::from(exec, index);\n");
2112 $generatedPropertyName = 1;
2115 if ($indexedGetterFunction) {
2116 if ($indexedGetterFunction->signature->type eq "DOMString") {
2117 push(@implContent, " if (index <= MAX_ARRAY_INDEX) {\n");
2119 push(@implContent, " if (index < thisObject->impl().length()) {\n");
2121 # Assume that if there's a setter, the index will be writable
2122 if ($interface->extendedAttributes->{"CustomIndexedSetter"}) {
2123 push(@implContent, " unsigned attributes = DontDelete;\n");
2125 push(@implContent, " unsigned attributes = DontDelete | ReadOnly;\n");
2127 push(@implContent, " slot.setValue(thisObject, attributes, " . GetIndexedGetterExpression($indexedGetterFunction) . ");\n");
2128 push(@implContent, " return true;\n");
2129 push(@implContent, " }\n");
2132 if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) {
2133 &$propertyNameGeneration();
2134 push(@implContent, " if (canGetItemsForName(exec, &thisObject->impl(), propertyName)) {\n");
2135 push(@implContent, " slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, thisObject->nameGetter);\n");
2136 push(@implContent, " return true;\n");
2137 push(@implContent, " }\n");
2138 $implIncludes{"wtf/text/AtomicString.h"} = 1;
2141 if ($interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) {
2142 &$propertyNameGeneration();
2143 push(@implContent, " if (thisObject->getOwnPropertySlotDelegate(exec, propertyName, slot))\n");
2144 push(@implContent, " return true;\n");
2147 push(@implContent, " return Base::getOwnPropertySlotByIndex(thisObject, exec, index, slot);\n");
2148 push(@implContent, "}\n\n");
2152 $numAttributes = $numAttributes + 1 if !$interface->extendedAttributes->{"NoInterfaceObject"};
2153 if ($numAttributes > 0) {
2154 foreach my $attribute (@{$interface->attributes}) {
2155 my $name = $attribute->signature->name;
2156 my $type = $attribute->signature->type;
2157 my $isNullable = $attribute->signature->isNullable;
2158 $codeGenerator->AssertNotSequenceType($type);
2159 my $getFunctionName = GetAttributeGetterName($interfaceName, $className, $attribute);
2160 my $implGetterFunctionName = $codeGenerator->WK_lcfirst($attribute->signature->extendedAttributes->{"ImplementedAs"} || $name);
2161 my $getterExceptions = $attribute->signature->extendedAttributes->{"GetterRaisesException"};
2163 my $attributeConditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
2164 push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
2166 push(@implContent, "EncodedJSValue ${getFunctionName}(ExecState* exec, JSObject* slotBase, EncodedJSValue thisValue, PropertyName)\n");
2167 push(@implContent, "{\n");
2169 push(@implContent, " UNUSED_PARAM(exec);\n");
2170 push(@implContent, " UNUSED_PARAM(slotBase);\n");
2171 push(@implContent, " UNUSED_PARAM(thisValue);\n");
2172 if (!$attribute->isStatic || $attribute->signature->type =~ /Constructor$/) {
2173 if ($interface->extendedAttributes->{"CustomProxyToJSObject"}) {
2174 push(@implContent, " ${className}* castedThis = to${className}(JSValue::decode(thisValue));\n");
2175 } elsif (AttributeShouldBeOnInstance($interface, $attribute)) {
2176 push(@implContent, " ${className}* castedThis = " . GetCastingHelperForBaseObject($interface) . "(slotBase);\n");
2177 if (InterfaceRequiresAttributesOnInstanceForCompatibility($interface)) {
2178 push(@implContent, " ${className}* castedThisObject = " . GetCastingHelperForThisObject($interface) . "(JSValue::decode(thisValue));\n");
2179 push(@implContent, " if (UNLIKELY(!castedThisObject))\n");
2180 push(@implContent, " reportDeprecatedGetterError(*exec, \"$interfaceName\", \"$name\");\n");
2183 push(@implContent, " ${className}* castedThis = " . GetCastingHelperForThisObject($interface) . "(JSValue::decode(thisValue));\n");
2184 push(@implContent, " if (UNLIKELY(!castedThis)) {\n");
2185 push(@implContent, " if (jsDynamicCast<${className}Prototype*>(slotBase))\n");
2186 push(@implContent, " return reportDeprecatedGetterError(*exec, \"$interfaceName\", \"$name\");\n");
2187 push(@implContent, " return throwGetterTypeError(*exec, \"$interfaceName\", \"$name\");\n");
2188 push(@implContent, " }\n");
2190 $implIncludes{"ScriptExecutionContext.h"} = 1;
2194 if ($getterExceptions && !HasCustomGetter($attribute->signature->extendedAttributes)) {
2195 push(@arguments, "ec");
2196 push(@implContent, " ExceptionCode ec = 0;\n");
2199 # Global constructors can be disabled at runtime.
2200 if ($attribute->signature->type =~ /Constructor$/) {
2201 if ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
2202 AddToImplIncludes("RuntimeEnabledFeatures.h");
2203 my $enable_function = GetRuntimeEnableFunctionName($attribute->signature);
2204 push(@implContent, " if (!${enable_function}())\n");
2205 push(@implContent, " return JSValue::encode(jsUndefined());\n");
2206 } elsif ($attribute->signature->extendedAttributes->{"EnabledBySetting"}) {
2207 AddToImplIncludes("Frame.h");
2208 AddToImplIncludes("Settings.h");
2209 my $enable_function = ToMethodName($attribute->signature->extendedAttributes->{"EnabledBySetting"}) . "Enabled";
2210 push(@implContent, " if (!castedThis->impl().frame())\n");
2211 push(@implContent, " return JSValue::encode(jsUndefined());\n");
2212 push(@implContent, " Settings& settings = castedThis->impl().frame()->settings();\n");
2213 push(@implContent, " if (!settings.$enable_function())\n");
2214 push(@implContent, " return JSValue::encode(jsUndefined());\n");
2218 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
2219 $needsVisitChildren = 1;
2222 if ($interface->extendedAttributes->{"CheckSecurity"} &&
2223 !$attribute->signature->extendedAttributes->{"DoNotCheckSecurity"} &&
2224 !$attribute->signature->extendedAttributes->{"DoNotCheckSecurityOnGetter"}) {
2225 push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n");
2226 push(@implContent, " return JSValue::encode(jsUndefined());\n");
2229 if ($attribute->signature->extendedAttributes->{"Nondeterministic"}) {
2230 AddToImplIncludes("MemoizedDOMResult.h", "WEB_REPLAY");
2231 AddToImplIncludes("<replay/InputCursor.h>", "WEB_REPLAY");
2232 AddToImplIncludes("<wtf/NeverDestroyed.h>", "WEB_REPLAY");
2234 push(@implContent, "#if ENABLE(WEB_REPLAY)\n");
2235 push(@implContent, " JSGlobalObject* globalObject = exec->lexicalGlobalObject();\n");
2236 push(@implContent, " InputCursor& cursor = globalObject->inputCursor();\n");
2238 my $nativeType = GetNativeType($type);
2239 my $memoizedType = GetNativeTypeForMemoization($type);
2240 my $exceptionCode = $getterExceptions ? "ec" : "0";
2241 push(@implContent, " static NeverDestroyed<const AtomicString> bindingName(\"$interfaceName.$name\", AtomicString::ConstructFromLiteral);\n");
2242 push(@implContent, " if (cursor.isCapturing()) {\n");
2243 push(@implContent, " $memoizedType memoizedResult = castedThis->impl().$implGetterFunctionName(" . join(", ", @arguments) . ");\n");
2244 push(@implContent, " cursor.appendInput<MemoizedDOMResult<$memoizedType>>(bindingName.get().string(), memoizedResult, $exceptionCode);\n");
2245 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "memoizedResult", "castedThis") . ";\n");
2246 push(@implContent, " setDOMException(exec, ec);\n") if $getterExceptions;
2247 push(@implContent, " return JSValue::encode(result);\n");
2248 push(@implContent, " }\n");
2249 push(@implContent, "\n");
2250 push(@implContent, " if (cursor.isReplaying()) {\n");
2251 push(@implContent, " $memoizedType memoizedResult;\n");
2252 push(@implContent, " MemoizedDOMResultBase* input = cursor.fetchInput<MemoizedDOMResultBase>();\n");
2253 push(@implContent, " if (input && input->convertTo<$memoizedType>(memoizedResult)) {\n");
2254 # FIXME: the generated code should report an error if an input cannot be fetched or converted.
2255 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "memoizedResult", "castedThis") . ";\n");
2256 push(@implContent, " setDOMException(exec, input->exceptionCode());\n") if $getterExceptions;
2257 push(@implContent, " return JSValue::encode(result);\n");
2258 push(@implContent, " }\n");
2259 push(@implContent, " }\n");
2260 push(@implContent, "#endif\n");
2261 } # attribute Nondeterministic
2263 if (HasCustomGetter($attribute->signature->extendedAttributes)) {
2264 push(@implContent, " return JSValue::encode(castedThis->$implGetterFunctionName(exec));\n");
2265 } elsif ($attribute->signature->extendedAttributes->{"CheckSecurityForNode"}) {
2266 $implIncludes{"JSDOMBinding.h"} = 1;
2267 push(@implContent, " $implType& impl = castedThis->impl();\n");
2268 push(@implContent, " return JSValue::encode(shouldAllowAccessToNode(exec, impl." . $attribute->signature->name . "()) ? " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName()", "castedThis") . " : jsNull());\n");
2269 } elsif ($type eq "EventListener") {
2270 $implIncludes{"EventListener.h"} = 1;
2271 push(@implContent, " UNUSED_PARAM(exec);\n");
2272 push(@implContent, " $implType& impl = castedThis->impl();\n");
2273 push(@implContent, " if (EventListener* listener = impl.$implGetterFunctionName()) {\n");
2274 push(@implContent, " if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n");
2275 if ($interfaceName eq "Document" || $codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) {
2276 push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(&impl))\n");
2278 push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(impl.scriptExecutionContext()))\n");
2280 push(@implContent, " return JSValue::encode(jsFunction);\n");
2281 push(@implContent, " }\n");
2282 push(@implContent, " }\n");
2283 push(@implContent, " return JSValue::encode(jsNull());\n");
2284 } elsif ($attribute->signature->type =~ /Constructor$/) {
2285 my $constructorType = $attribute->signature->type;
2286 $constructorType =~ s/Constructor$//;
2287 # When Constructor attribute is used by DOMWindow.idl, it's correct to pass castedThis as the global object
2288 # When JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject()
2289 if ($interfaceName eq "DOMWindow") {
2290 my $named = ($constructorType =~ /Named$/) ? "Named" : "";
2291 $constructorType =~ s/Named$//;
2292 push(@implContent, " return JSValue::encode(JS" . $constructorType . "::get${named}Constructor(exec->vm(), castedThis));\n");
2294 AddToImplIncludes("JS" . $constructorType . ".h", $attribute->signature->extendedAttributes->{"Conditional"});
2295 push(@implContent, " return JSValue::encode(JS" . $constructorType . "::getConstructor(exec->vm(), castedThis->globalObject()));\n");
2297 } elsif (!$attribute->signature->extendedAttributes->{"GetterRaisesException"}) {
2298 push(@implContent, " bool isNull = false;\n") if $isNullable;
2301 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
2302 $cacheIndex = $currentCachedAttribute;
2303 $currentCachedAttribute++;
2304 push(@implContent, " if (JSValue cachedValue = castedThis->m_" . $attribute->signature->name . ".get())\n");
2305 push(@implContent, " return JSValue::encode(cachedValue);\n");
2308 my @callWithArgs = GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, "JSValue::encode(jsUndefined())");
2310 if ($svgListPropertyType) {
2311 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "castedThis->impl().$implGetterFunctionName(" . (join ", ", @callWithArgs) . ")", "castedThis") . ";\n");
2312 } elsif ($svgPropertyOrListPropertyType) {
2313 push(@implContent, " $svgPropertyOrListPropertyType& impl = castedThis->impl().propertyReference();\n");
2314 if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber
2315 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl", "castedThis") . ";\n");
2317 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName(" . (join ", ", @callWithArgs) . ")", "castedThis") . ";\n");
2321 my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
2322 push(@arguments, "isNull") if $isNullable;
2323 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
2324 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
2325 $implIncludes{"${implementedBy}.h"} = 1;
2326 $functionName = "${implementedBy}::${functionName}";
2327 unshift(@arguments, "&impl") if !$attribute->isStatic;
2328 } elsif ($attribute->isStatic) {
2329 $functionName = "${interfaceName}::${functionName}";
2331 $functionName = "impl.${functionName}";
2334 unshift(@arguments, @callWithArgs);
2335 my $jsType = NativeToJSValue($attribute->signature, 0, $interfaceName, "${functionName}(" . join(", ", @arguments) . ")", "castedThis");
2336 push(@implContent, " $implType& impl = castedThis->impl();\n") if !$attribute->isStatic;
2337 if ($codeGenerator->IsSVGAnimatedType($type)) {
2338 push(@implContent, " RefPtr<$type> obj = $jsType;\n");
2339 push(@implContent, " JSValue result = toJS(exec, castedThis->globalObject(), obj.get());\n");
2341 push(@implContent, " JSValue result = $jsType;\n");
2345 push(@implContent, " if (isNull)\n");
2346 push(@implContent, " return JSValue::encode(jsNull());\n");
2350 push(@implContent, " castedThis->m_" . $attribute->signature->name . ".set(exec->vm(), castedThis, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"});
2351 push(@implContent, " return JSValue::encode(result);\n");
2355 push(@implContent, " bool isNull = false;\n");
2356 unshift(@arguments, "isNull");
2359 unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, "JSValue::encode(jsUndefined())"));
2361 if ($svgPropertyOrListPropertyType) {
2362 push(@implContent, " $svgPropertyOrListPropertyType impl(*castedThis->impl());\n");
2363 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName(" . join(", ", @arguments) . ")", "castedThis") . ";\n");
2365 push(@implContent, " $implType& impl = castedThis->impl();\n");
2366 push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName(" . join(", ", @arguments) . ")", "castedThis") . ";\n");
2369 push(@implContent, " setDOMException(exec, ec);\n");
2372 push(@implContent, " if (isNull)\n");
2373 push(@implContent, " return JSValue::encode(jsNull());\n");
2376 push(@implContent, " return JSValue::encode(result);\n");
2379 push(@implContent, "}\n\n");
2381 push(@implContent, "#endif\n") if $attributeConditionalString;
2383 push(@implContent, "\n");
2386 if (!$interface->extendedAttributes->{"NoInterfaceObject"}) {
2387 my $constructorFunctionName = "js" . $interfaceName . "Constructor";
2389 if ($interface->extendedAttributes->{"CustomProxyToJSObject"}) {
2390 push(@implContent, "EncodedJSValue ${constructorFunctionName}(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName)\n");
2391 push(@implContent, "{\n");
2392 push(@implContent, " ${className}* domObject = to${className}(JSValue::decode(thisValue));\n");
2393 } elsif (ConstructorShouldBeOnInstance($interface)) {
2394 push(@implContent, "EncodedJSValue ${constructorFunctionName}(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName)\n");
2395 push(@implContent, "{\n");
2396 push(@implContent, " ${className}* domObject = " . GetCastingHelperForThisObject($interface) . "(JSValue::decode(thisValue));\n");
2398 push(@implContent, "EncodedJSValue ${constructorFunctionName}(ExecState* exec, JSObject* baseValue, EncodedJSValue, PropertyName)\n");
2399 push(@implContent, "{\n");
2400 push(@implContent, " ${className}Prototype* domObject = jsDynamicCast<${className}Prototype*>(baseValue);\n");
2402 push(@implContent, " if (!domObject)\n");
2403 push(@implContent, " return throwVMTypeError(exec);\n");
2405 if ($interface->extendedAttributes->{"CheckSecurity"}) {
2406 die if !ConstructorShouldBeOnInstance($interface);
2407 push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, domObject->impl()))\n");
2408 push(@implContent, " return JSValue::encode(jsUndefined());\n");
2411 push(@implContent, " return JSValue::encode(${className}::getConstructor(exec->vm(), domObject->globalObject()));\n");
2412 push(@implContent, "}\n\n");
2415 if ($interface->extendedAttributes->{"ReplaceableConstructor"}) {
2416 my $constructorFunctionName = "setJS" . $interfaceName . "Constructor";
2418 push(@implContent, "void ${constructorFunctionName}(ExecState* exec, JSObject*, EncodedJSValue thisValue, EncodedJSValue encodedValue)\n");
2419 push(@implContent, "{\n");
2420 push(@implContent, " JSValue value = JSValue::decode(encodedValue);");
2421 if ($interface->extendedAttributes->{"CustomProxyToJSObject"}) {
2422 push(@implContent, " ${className}* castedThis = to${className}(JSValue::decode(thisValue));\n");
2424 push(@implContent, " ${className}* castedThis = " . GetCastingHelperForThisObject($interface) . "(JSValue::decode(thisValue));\n");
2426 push(@implContent, " if (UNLIKELY(!castedThis)) {\n");
2427 push(@implContent, " throwVMTypeError(exec);\n");
2428 push(@implContent, " return;\n");
2429 push(@implContent, " }\n");
2430 if ($interface->extendedAttributes->{"CheckSecurity"}) {
2431 if ($interfaceName eq "DOMWindow") {
2432 push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n");
2434 push(@implContent, " if (!shouldAllowAccessToFrame(exec, castedThis->impl().frame()))\n");
2436 push(@implContent, " return;\n");
2439 push(@implContent, " // Shadowing a built-in constructor\n");
2441 if ($interfaceName eq "DOMWindow") {
2442 push(@implContent, " castedThis->putDirect(exec->vm(), exec->propertyNames().constructor, value);\n");
2444 die "No way to handle interface with ReplaceableConstructor extended attribute: $interfaceName";
2446 push(@implContent, "}\n\n");
2449 my $hasCustomSetter = $interface->extendedAttributes->{"CustomNamedSetter"}
2450 || $interface->extendedAttributes->{"CustomIndexedSetter"};
2452 if ($hasCustomSetter) {
2453 if (!$interface->extendedAttributes->{"CustomPutFunction"}) {
2454 push(@implContent, "void ${className}::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\n");
2455 push(@implContent, "{\n");
2456 push(@implContent, " ${className}* thisObject = jsCast<${className}*>(cell);\n");
2457 push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n");
2458 if ($interface->extendedAttributes->{"CustomIndexedSetter"}) {
2459 push(@implContent, " unsigned index = propertyName.asIndex();\n");
2460 push(@implContent, " if (index != PropertyName::NotAnIndex) {\n");
2461 push(@implContent, " thisObject->indexSetter(exec, index, value);\n");
2462 push(@implContent, " return;\n");
2463 push(@implContent, " }\n");
2465 if ($interface->extendedAttributes->{"CustomNamedSetter"}) {
2466 push(@implContent, " if (thisObject->putDelegate(exec, propertyName, value, slot))\n");
2467 push(@implContent, " return;\n");
2470 push(@implContent, " Base::put(thisObject, exec, propertyName, value, slot);\n");
2471 push(@implContent, "}\n\n");
2473 if ($interface->extendedAttributes->{"CustomIndexedSetter"} || $interface->extendedAttributes->{"CustomNamedSetter"}) {
2474 push(@implContent, "void ${className}::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow)\n");
2475 push(@implContent, "{\n");
2476 push(@implContent, " ${className}* thisObject = jsCast<${className}*>(cell);\n");
2477 push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n");
2479 if ($interface->extendedAttributes->{"CustomIndexedSetter"}) {
2480 push(@implContent, " if (index <= MAX_ARRAY_INDEX) {\n");
2481 push(@implContent, " thisObject->indexSetter(exec, index, value);\n");
2482 push(@implContent, " return;\n");
2483 push(@implContent, " }\n");
2486 if ($interface->extendedAttributes->{"CustomNamedSetter"}) {
2487 push(@implContent, " PropertyName propertyName = Identifier::from(exec, index);\n");
2488 push(@implContent, " PutPropertySlot slot(thisObject, shouldThrow);\n");
2489 push(@implContent, " if (thisObject->putDelegate(exec, propertyName, value, slot))\n");
2490 push(@implContent, " return;\n");
2493 push(@implContent, " Base::putByIndex(cell, exec, index, value, shouldThrow);\n");
2494 push(@implContent, "}\n\n");
2499 # Check if we have any writable attributes
2500 my $hasReadWriteProperties = 0;
2501 foreach my $attribute (@{$interface->attributes}) {
2502 $hasReadWriteProperties = 1 if !IsReadonly($attribute) && !$attribute->isStatic;
2504 if ($attribute->signature->type eq "EventListener") {
2505 $implIncludes{"JSEventListener.h"} = 1;
2509 if ($hasReadWriteProperties) {
2510 foreach my $attribute (@{$interface->attributes}) {
2511 if (!IsReadonly($attribute)) {
2512 my $name = $attribute->signature->name;
2513 my $type = $attribute->signature->type;
2514 my $putFunctionName = GetAttributeSetterName($interfaceName, $className, $attribute);
2515 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name);
2516 my $setterRaisesException = $attribute->signature->extendedAttributes->{"SetterRaisesException"};
2518 my $attributeConditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
2519 push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
2521 push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* baseObject, EncodedJSValue");
2522 push(@implContent, " thisValue") if !$attribute->isStatic;
2523 push(@implContent, ", EncodedJSValue encodedValue)\n");
2524 push(@implContent, "{\n");
2525 push(@implContent, " JSValue value = JSValue::decode(encodedValue);\n");
2526 push(@implContent, " UNUSED_PARAM(baseObject);\n");
2527 if (!$attribute->isStatic) {
2528 if ($interface->extendedAttributes->{"CustomProxyToJSObject"}) {
2529 push(@implContent, " ${className}* castedThis = to${className}(JSValue::decode(thisValue));\n");
2530 } elsif (AttributeShouldBeOnInstance($interface, $attribute)) {
2531 push(@implContent, " UNUSED_PARAM(thisValue);\n");
2532 push(@implContent, " ${className}* castedThis = " . GetCastingHelperForBaseObject($interface) . "(baseObject);\n");
2533 if (InterfaceRequiresAttributesOnInstanceForCompatibility($interface)) {
2534 push(@implContent, " ${className}* castedThisObject = " . GetCastingHelperForThisObject($interface) . "(JSValue::decode(thisValue));\n");
2535 push(@implContent, " if (UNLIKELY(!castedThisObject))\n");
2536 push(@implContent, " reportDeprecatedSetterError(*exec, \"$interfaceName\", \"$name\");\n");
2538 push(@implContent, " UNUSED_PARAM(thisValue);\n");
2539 push(@implContent, " UNUSED_PARAM(exec);\n");
2542 push(@implContent, " ${className}* castedThis = " . GetCastingHelperForThisObject($interface) . "(JSValue::decode(thisValue));\n");
2543 push(@implContent, " if (UNLIKELY(!castedThis)) {\n");
2544 push(@implContent, " if (jsDynamicCast<${className}Prototype*>(JSValue::decode(thisValue)))\n");
2545 push(@implContent, " reportDeprecatedSetterError(*exec, \"$interfaceName\", \"$name\");\n");
2546 push(@implContent, " else\n");
2547 push(@implContent, " throwSetterTypeError(*exec, \"$interfaceName\", \"$name\");\n");
2548 push(@implContent, " return;\n");
2549 push(@implContent, " }\n");
2552 if ($interface->extendedAttributes->{"CheckSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2553 if ($interfaceName eq "DOMWindow") {
2554 push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n");
2556 push(@implContent, " if (!shouldAllowAccessToFrame(exec, castedThis->impl().frame()))\n");
2558 push(@implContent, " return;\n");
2561 if (HasCustomSetter($attribute->signature->extendedAttributes)) {
2562 push(@implContent, " castedThis->set$implSetterFunctionName(exec, value);\n");
2563 } elsif ($type eq "EventListener") {
2564 $implIncludes{"JSEventListener.h"} = 1;
2565 push(@implContent, " UNUSED_PARAM(exec);\n");
2566 my $windowEventListener = $attribute->signature->extendedAttributes->{"JSWindowEventListener"};
2567 if ($windowEventListener) {
2568 push(@implContent, " JSDOMGlobalObject* globalObject = castedThis->globalObject();\n");
2570 push(@implContent, " $implType& impl = castedThis->impl();\n");
2571 if ((($interfaceName eq "DOMWindow") or ($interfaceName eq "WorkerGlobalScope")) and $name eq "onerror") {
2572 $implIncludes{"JSErrorHandler.h"} = 1;
2573 push(@implContent, " impl.set$implSetterFunctionName(createJSErrorHandler(exec, value, castedThis));\n");
2575 push(@implContent, GenerateAttributeEventListenerCall($implSetterFunctionName, $windowEventListener));
2577 } elsif ($attribute->signature->type =~ /Constructor$/) {
2578 my $constructorType = $attribute->signature->type;
2579 $constructorType =~ s/Constructor$//;
2580 # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
2581 # We do not generate the header file for NamedConstructor of class XXXX,
2582 # since we generate the NamedConstructor declaration into the header file of class XXXX.
2583 if ($constructorType ne "any" and $constructorType !~ /Named$/) {
2584 AddToImplIncludes("JS" . $constructorType . ".h", $attribute->signature->extendedAttributes->{"Conditional"});
2586 push(@implContent, " // Shadowing a built-in constructor\n");
2587 push(@implContent, " castedThis->putDirect(exec->vm(), Identifier(exec, \"$name\"), value);\n");
2588 } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
2589 push(@implContent, " // Shadowing a built-in object\n");
2590 push(@implContent, " castedThis->putDirect(exec->vm(), Identifier(exec, \"$name\"), value);\n");
2592 if (!$attribute->isStatic) {
2593 push(@implContent, " $implType& impl = castedThis->impl();\n");
2595 push(@implContent, " ExceptionCode ec = 0;\n") if $setterRaisesException;
2597 # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
2598 # interface type, then if the incoming value does not implement that interface, a TypeError
2599 # is thrown rather than silently passing NULL to the C++ code.
2600 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to
2601 # both strings and numbers, so do not throw TypeError if the attribute is of these types.
2602 if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
2603 $implIncludes{"<runtime/Error.h>"} = 1;
2605 my $argType = $attribute->signature->type;
2606 if ($codeGenerator->IsWrapperType($argType)) {
2607 push(@implContent, " if (!value.isUndefinedOrNull() && !value.inherits(JS${argType}::info())) {\n");
2608 push(@implContent, " throwAttributeTypeError(*exec, \"$interfaceName\", \"$name\", \"$argType\");\n");
2609 push(@implContent, " return;\n");
2610 push(@implContent, " };\n");
2614 push(@implContent, " " . GetNativeTypeFromSignature($attribute->signature) . " nativeValue(" . JSValueToNative($attribute->signature, "value") . ");\n");
2615 push(@implContent, " if (UNLIKELY(exec->hadException()))\n");
2616 push(@implContent, " return;\n");
2618 if ($codeGenerator->IsEnumType($type)) {
2619 my @enumValues = $codeGenerator->ValidEnumValues($type);
2620 my @enumChecks = ();
2621 foreach my $enumValue (@enumValues) {
2622 push(@enumChecks, "nativeValue != \"$enumValue\"");
2624 push (@implContent, " if (" . join(" && ", @enumChecks) . ")\n");
2625 push (@implContent, " return;\n");
2628 if ($attribute->signature->type eq "double" or $attribute->signature->type eq "float") {
2629 push(@implContent, " if (!std::isfinite(nativeValue)) {\n");
2630 push(@implContent, " setDOMException(exec, TypeError);\n");
2631 push(@implContent, " return;\n");
2632 push(@implContent, " }\n");
2635 if ($svgPropertyOrListPropertyType) {
2636 if ($svgPropertyType) {
2637 push(@implContent, " if (impl.isReadOnly()) {\n");
2638 push(@implContent, " setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");
2639 push(@implContent, " return;\n");
2640 push(@implContent, " }\n");
2641 $implIncludes{"ExceptionCode.h"} = 1;
2643 push(@implContent, " $svgPropertyOrListPropertyType& podImpl = impl.propertyReference();\n");
2644 if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber
2645 push(@implContent, " podImpl = nativeValue;\n");
2647 push(@implContent, " podImpl.set$implSetterFunctionName(nativeValue");
2648 push(@implContent, ", ec") if $setterRaisesException;
2649 push(@implContent, ");\n");
2650 push(@implContent, " setDOMException(exec, ec);\n") if $setterRaisesException;
2652 if ($svgPropertyType) {
2653 if ($setterRaisesException) {
2654 push(@implContent, " if (!ec)\n");
2655 push(@implContent, " impl.commitChange();\n");
2657 push(@implContent, " impl.commitChange();\n");
2661 my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute);
2662 if ($codeGenerator->IsTypedArrayType($attribute->signature->type) and not $attribute->signature->type eq "ArrayBuffer") {
2663 push(@arguments, "nativeValue.get()");
2665 push(@arguments, "nativeValue");
2667 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
2668 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
2669 $implIncludes{"${implementedBy}.h"} = 1;
2670 unshift(@arguments, "&impl") if !$attribute->isStatic;
2671 $functionName = "${implementedBy}::${functionName}";
2672 } elsif ($attribute->isStatic) {
2673 $functionName = "${interfaceName}::${functionName}";
2675 $functionName = "impl.${functionName}";
2678 unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, ""));
2680 push(@arguments, "ec") if $setterRaisesException;
2681 push(@implContent, " ${functionName}(" . join(", ", @arguments) . ");\n");
2682 push(@implContent, " setDOMException(exec, ec);\n") if $setterRaisesException;
2686 push(@implContent, "}\n\n");
2687 push(@implContent, "#endif\n") if $attributeConditionalString;
2688 push(@implContent, "\n");
2693 if ($indexedGetterFunction && !$interface->extendedAttributes->{"CustomEnumerateProperty"}) {
2694 push(@implContent, "void ${className}::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n");
2695 push(@implContent, "{\n");
2696 push(@implContent, " ${className}* thisObject = jsCast<${className}*>(object);\n");
2697 push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n");
2698 push(@implContent, " for (unsigned i = 0, count = thisObject->impl().length(); i < count; ++i)\n");
2699 push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n");
2700 push(@implContent, " Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);\n");
2701 push(@implContent, "}\n\n");
2704 if (!$interface->extendedAttributes->{"NoInterfaceObject"}) {
2705 push(@implContent, "JSValue ${className}::getConstructor(VM& vm, JSGlobalObject* globalObject)\n{\n");
2706 push(@implContent, " return getDOMConstructor<${className}Constructor>(vm, jsCast<JSDOMGlobalObject*>(globalObject));\n");
2707 push(@implContent, "}\n\n");
2708 if ($interface->extendedAttributes->{"NamedConstructor"}) {
2709 push(@implContent, "JSValue ${className}::getNamedConstructor(VM& vm, JSGlobalObject* globalObject)\n{\n");
2710 push(@implContent, " return getDOMConstructor<${className}NamedConstructor>(vm, jsCast<JSDOMGlobalObject*>(globalObject));\n");
2711 push(@implContent, "}\n\n");
2716 if ($numFunctions > 0) {
2717 my $inAppleCopyright = 0;
2718 foreach my $function (@{$interface->functions}) {
2719 my $needsAppleCopyright = $function->signature->extendedAttributes->{"AppleCopyright"};
2720 if ($needsAppleCopyright) {
2721 if (!$inAppleCopyright) {
2722 push(@implContent, $beginAppleCopyrightForSourceFiles);
2723 $inAppleCopyright = 1;
2725 } elsif ($inAppleCopyright) {
2726 push(@implContent, $endAppleCopyright);
2727 $inAppleCopyright = 0;
2730 my $isCustom = HasCustomMethod($function->signature->extendedAttributes);
2731 my $isOverloaded = $function->{overloads} && @{$function->{overloads}} > 1;
2732 my $raisesException = $function->signature->extendedAttributes->{"RaisesException"};
2734 next if $isCustom && $isOverloaded && $function->{overloadIndex} > 1;
2736 AddIncludesForTypeInImpl($function->signature->type) unless $isCustom;
2738 my $functionName = GetFunctionName($className, $function);
2740 my $conditional = $function->signature->extendedAttributes->{"Conditional"};
2742 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2743 push(@implContent, "#if ${conditionalString}\n");
2747 if (!$isCustom && $isOverloaded) {
2748 # Append a number to an overloaded method's name to make it unique:
2749 $functionName = $functionName . $function->{overloadIndex};
2750 # Make this function static to avoid compiler warnings, since we
2751 # don't generate a prototype for it in the header.
2752 push(@implContent, "static ");
2755 my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $codeGenerator->WK_lcfirst($function->signature->name);
2757 push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n");
2758 push(@implContent, "{\n");
2760 $implIncludes{"<runtime/Error.h>"} = 1;
2762 if ($function->isStatic) {
2764 GenerateArgumentsCountCheck(\@implContent, $function, $interface);
2765 push(@implContent, " return JSValue::encode(${className}::" . $functionImplementationName . "(exec));\n");
2767 GenerateArgumentsCountCheck(\@implContent, $function, $interface);
2769 push(@implContent, " ExceptionCode ec = 0;\n") if $raisesException;
2771 my $numParameters = @{$function->parameters};
2772 my ($functionString, $dummy) = GenerateParametersCheck(\@implContent, $function, $interface, $numParameters, $interfaceName, $functionImplementationName, $svgPropertyType, $svgPropertyOrListPropertyType, $svgListPropertyType);
2773 GenerateImplementationFunctionCall($function, $functionString, " ", $svgPropertyType, $interfaceName);
2776 if ($interface->extendedAttributes->{"CustomProxyToJSObject"}) {
2777 push(@implContent, " $className* castedThis = to${className}(exec->thisValue().toThis(exec, NotStrictMode));\n");
2778 push(@implContent, " if (UNLIKELY(!castedThis))\n");
2779 push(@implContent, " return throwVMTypeError(exec);\n");
2780 } elsif ($interface->extendedAttributes->{"WorkerGlobalScope"}) {
2781 push(@implContent, " $className* castedThis = to${className}(exec->thisValue().toThis(exec, NotStrictMode));\n");
2782 push(@implContent, " if (UNLIKELY(!castedThis))\n");
2783 push(@implContent, " return throwVMTypeError(exec);\n");
2785 push(@implContent, " JSValue thisValue = exec->thisValue();\n");
2786 push(@implContent, " $className* castedThis = " . GetCastingHelperForThisObject($interface) . "(thisValue);\n");
2787 my $domFunctionName = $function->signature->name;
2788 push(@implContent, " if (UNLIKELY(!castedThis))\n");
2789 push(@implContent, " return throwThisTypeError(*exec, \"$interfaceName\", \"$domFunctionName\");\n");
2792 push(@implContent, " ASSERT_GC_OBJECT_INHERITS(castedThis, ${className}::info());\n");
2794 if ($interface->extendedAttributes->{"CheckSecurity"} and
2795 !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2796 push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n");
2797 push(@implContent, " return JSValue::encode(jsUndefined());\n");
2801 push(@implContent, " return JSValue::encode(castedThis->" . $functionImplementationName . "(exec));\n");
2803 push(@implContent, " $implType& impl = castedThis->impl();\n");
2804 if ($svgPropertyType) {
2805 push(@implContent, " if (impl.isReadOnly()) {\n");
2806 push(@implContent, " setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n");
2807 push(@implContent, " return JSValue::encode(jsUndefined());\n");
2808 push(@implContent, " }\n");
2809 push(@implContent, " $svgPropertyType& podImpl = impl.propertyReference();\n");
2810 $implIncludes{"ExceptionCode.h"} = 1;
2813 # For compatibility with legacy content, the EventListener calls are generated without GenerateArgumentsCountCheck.
2814 if ($function->signature->name eq "addEventListener") {
2815 push(@implContent, GenerateEventListenerCall("add"));
2816 } elsif ($function->signature->name eq "removeEventListener") {
2817 push(@implContent, GenerateEventListenerCall("remove"));
2819 GenerateArgumentsCountCheck(\@implContent, $function, $interface);
2821 push(@implContent, " ExceptionCode ec = 0;\n") if $raisesException;
2823 if ($function->signature->extendedAttributes->{"CheckSecurityForNode"}) {
2824 push(@implContent, " if (!shouldAllowAccessToNode(exec, impl." . $function->signature->name . "(" . ($raisesException ? "ec" : "") .")))\n");
2825 push(@implContent, " return JSValue::encode(jsNull());\n");
2826 $implIncludes{"JSDOMBinding.h"} = 1;
2829 my $numParameters = @{$function->parameters};
2830 my ($functionString, $dummy) = GenerateParametersCheck(\@implContent, $function, $interface, $numParameters, $interfaceName, $functionImplementationName, $svgPropertyType, $svgPropertyOrListPropertyType, $svgListPropertyType);
2831 GenerateImplementationFunctionCall($function, $functionString, " ", $svgPropertyType, $interfaceName);
2836 push(@implContent, "}\n\n");
2837 push(@implContent, "#endif\n\n") if $conditional;
2839 if (!$isCustom && $isOverloaded && $function->{overloadIndex} == @{$function->{overloads}}) {
2840 # Generate a function dispatching call to the rest of the overloads.
2841 GenerateOverloadedFunction($function, $interface, $interfaceName);
2846 push(@implContent, $endAppleCopyright) if $inAppleCopyright;
2850 if ($needsVisitChildren) {
2851 push(@implContent, "void ${className}::visitChildren(JSCell* cell, SlotVisitor& visitor)\n");
2852 push(@implContent, "{\n");
2853 push(@implContent, " ${className}* thisObject = jsCast<${className}*>(cell);\n");
2854 push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n");
2855 push(@implContent, " Base::visitChildren(thisObject, visitor);\n");
2856 if ($interface->extendedAttributes->{"EventTarget"} || $interface->name eq "EventTarget") {
2857 push(@implContent, " thisObject->impl().visitJSEventListeners(visitor);\n");
2859 push(@implContent, " thisObject->visitAdditionalChildren(visitor);\n") if $interface->extendedAttributes->{"JSCustomMarkFunction"};
2860 if ($interface->extendedAttributes->{"ReportExtraMemoryCost"}) {
2861 push(@implContent, " visitor.reportExtraMemoryUsage(cell, thisObject->impl().memoryCost());\n");
2863 if ($numCachedAttributes > 0) {
2864 foreach (@{$interface->attributes}) {
2866 if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) {
2867 push(@implContent, " visitor.append(&thisObject->m_" . $attribute->signature->name . ");\n");
2871 push(@implContent, "}\n\n");
2874 # Cached attributes are indeed allowed when there is a custom mark/visitChildren function.
2875 # The custom function must make sure to account for the cached attribute.
2876 # Uncomment the below line to temporarily enforce generated mark functions when cached attributes are present.
2877 # die "Can't generate binding for class with cached attribute and custom mark." if (($numCachedAttributes > 0) and ($interface->extendedAttributes->{"JSCustomMarkFunction"}));
2879 if ($indexedGetterFunction) {
2880 if ($indexedGetterFunction->signature->type eq "DOMString") {
2881 $implIncludes{"URL.h"} = 1;
2883 if ($interfaceName =~ /^HTML\w*Collection$/ or $interfaceName eq "RadioNodeList") {
2884 $implIncludes{"JSNode.h"} = 1;
2885 $implIncludes{"Node.h"} = 1;
2889 if ($interfaceName eq "DOMNamedFlowCollection") {
2890 if ($namedGetterFunction) {
2891 push(@implContent, "bool ${className}::canGetItemsForName(ExecState*, $interfaceName* collection, PropertyName propertyName)\n");
2892 push(@implContent, "{\n");
2893 push(@implContent, " return collection->hasNamedItem(propertyNameToAtomicString(propertyName));\n");
2894 push(@implContent, "}\n\n");
2895 push(@implContent, "EncodedJSValue ${className}::nameGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName propertyName)\n");
2896 push(@implContent, "{\n");
2897 push(@implContent, " ${className}* thisObj = jsCast<$className*>(slotBase);\n");
2898 push(@implContent, " return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName))));\n");
2899 push(@implContent, "}\n\n");
2903 if ((!$hasParent && !GetCustomIsReachable($interface)) || GetGenerateIsReachable($interface) || $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
2904 if (GetGenerateIsReachable($interface)) {
2905 push(@implContent, "static inline bool isObservable(JS${interfaceName}* js${interfaceName})\n");
2906 push(@implContent, "{\n");
2907 push(@implContent, " if (js${interfaceName}->hasCustomProperties())\n");
2908 push(@implContent, " return true;\n");
2910 push(@implContent, " if (js${interfaceName}->impl().hasEventListeners())\n");
2911 push(@implContent, " return true;\n");
2913 push(@implContent, " return false;\n");
2914 push(@implContent, "}\n\n");
2917 push(@implContent, "bool JS${interfaceName}Owner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)\n");
2918 push(@implContent, "{\n");
2919 # All ActiveDOMObjects implement hasPendingActivity(), but not all of them
2920 # increment their C++ reference counts when hasPendingActivity() becomes
2921 # true. As a result, ActiveDOMObjects can be prematurely destroyed before
2922 # their pending activities complete. To wallpaper over this bug, JavaScript
2923 # wrappers unconditionally keep ActiveDOMObjects with pending activity alive.
2924 # FIXME: Fix this lifetime issue in the DOM, and move this hasPendingActivity
2925 # check below the isObservable check.
2926 my $emittedJSCast = 0;
2927 if ($codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
2928 push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.slot()->asCell());\n");
2930 push(@implContent, " if (js${interfaceName}->impl().hasPendingActivity())\n");
2931 push(@implContent, " return true;\n");
2933 if ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
2934 if (!$emittedJSCast) {
2935 push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.slot()->asCell());\n");
2938 push(@implContent, " if (js${interfaceName}->impl().isFiringEventListeners())\n");
2939 push(@implContent, " return true;\n");
2941 if ($codeGenerator->InheritsInterface($interface, "Node")) {
2942 if (!$emittedJSCast) {
2943 push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.slot()->asCell());\n");
2946 push(@implContent, " if (JSNodeOwner::isReachableFromOpaqueRoots(handle, 0, visitor))\n");
2947 push(@implContent, " return true;\n");
2949 if (GetGenerateIsReachable($interface)) {
2950 if (!$emittedJSCast) {
2951 push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.slot()->asCell());\n");
2954 push(@implContent, " if (!isObservable(js${interfaceName}))\n");
2955 push(@implContent, " return false;\n");
2958 if (GetGenerateIsReachable($interface) eq "Impl") {
2959 $rootString = " ${implType}* root = &js${interfaceName}->impl();\n";
2960 } elsif (GetGenerateIsReachable($interface) eq "ImplWebGLRenderingContext") {
2961 $rootString = " WebGLRenderingContext* root = WTF::getPtr(js${interfaceName}->impl().context());\n";
2962 } elsif (GetGenerateIsReachable($interface) eq "ImplFrame") {
2963 $rootString = " Frame* root = WTF::getPtr(js${interfaceName}->impl().frame());\n";
2964 $rootString .= " if (!root)\n";
2965 $rootString .= " return false;\n";