2 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006 Apple Computer, Inc.
7 # Copyright (C) 2007, 2008, 2009 Google Inc.
8 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
9 # Copyright (C) Research In Motion Limited 2010. All rights reserved.
11 # This library is free software; you can redistribute it and/or
12 # modify it under the terms of the GNU Library General Public
13 # License as published by the Free Software Foundation; either
14 # version 2 of the License, or (at your option) any later version.
16 # This library is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 # Library General Public License for more details.
21 # You should have received a copy of the GNU Library General Public License
22 # along with this library; see the file COPYING.LIB. If not, write to
23 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 # Boston, MA 02111-1307, USA.
27 package CodeGeneratorV8;
34 my $outputHeadersDir = "";
36 my @headerContent = ();
37 my @implContentHeader = ();
38 my @implFixedHeader = ();
40 my @implContentDecls = ();
41 my %implIncludes = ();
46 my $headerTemplate = << "EOF";
48 This file is part of the WebKit open source project.
49 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
51 This library is free software; you can redistribute it and/or
52 modify it under the terms of the GNU Library General Public
53 License as published by the Free Software Foundation; either
54 version 2 of the License, or (at your option) any later version.
56 This library is distributed in the hope that it will be useful,
57 but WITHOUT ANY WARRANTY; without even the implied warranty of
58 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
59 Library General Public License for more details.
61 You should have received a copy of the GNU Library General Public License
62 along with this library; see the file COPYING.LIB. If not, write to
63 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
64 Boston, MA 02111-1307, USA.
74 $codeGenerator = shift;
76 $outputHeadersDir = shift;
78 bless($reference, $object);
90 # Workaround for V8 bindings difference where RGBColor is not a POD type.
91 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
95 return $codeGenerator->IsPodType($type);
98 # Params: 'domClass' struct
102 my $dataNode = shift;
105 # Start actual generation
106 if ($dataNode->extendedAttributes->{"Callback"}) {
107 $object->GenerateCallbackHeader($dataNode);
108 $object->GenerateCallbackImplementation($dataNode);
110 $object->GenerateHeader($dataNode);
111 $object->GenerateImplementation($dataNode);
114 my $name = $dataNode->name;
116 # Open files for writing
117 my $headerFileName = "$outputHeadersDir/V8$name.h";
118 my $implFileName = "$outputDir/V8$name.cpp";
120 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
121 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
124 # Params: 'idlDocument' struct
128 my $dataNode = shift;
130 $module = $dataNode->module;
133 sub AddIncludesForType
135 my $type = $codeGenerator->StripModule(shift);
137 # When we're finished with the one-file-per-class
138 # reorganization, we won't need these special cases.
139 if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->AvoidInclusionOfType($type) and $type ne "Date") {
140 # default, include the same named file
141 $implIncludes{GetV8HeaderName(${type})} = 1;
143 if ($type =~ /SVGPathSeg/) {
145 $joinedName =~ s/Abs|Rel//;
146 $implIncludes{"${joinedName}.h"} = 1;
150 # additional includes (things needed to compile the bindings but not the header)
152 if ($type eq "CanvasRenderingContext2D") {
153 $implIncludes{"CanvasGradient.h"} = 1;
154 $implIncludes{"CanvasPattern.h"} = 1;
155 $implIncludes{"CanvasStyle.h"} = 1;
158 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
159 $implIncludes{"PlatformString.h"} = 1;
162 if ($type eq "CSSStyleDeclaration") {
163 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
166 if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
167 # So we can get String -> AtomicString conversion for namedItem().
168 $implIncludes{"wtf/text/AtomicString.h"} = 1;
172 sub AddIncludesForSVGAnimatedType
175 return if $codeGenerator->IsSVGNewStyleAnimatedType($type);
177 $type =~ s/SVGAnimated//;
179 if ($type eq "Point" or $type eq "Rect") {
180 $implIncludes{"Float$type.h"} = 1;
181 } elsif ($type eq "String") {
182 $implIncludes{"PlatformString.h"} = 1;
185 $implIncludes{"DeprecatedSVGAnimatedTemplate.h"} = 1;
188 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
189 sub GenerateConditionalString
192 my $conditional = $node->extendedAttributes->{"Conditional"};
194 if ($conditional =~ /&/) {
195 return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
196 } elsif ($conditional =~ /\|/) {
197 return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
199 return "ENABLE(" . $conditional . ")";
206 sub GetSVGPropertyTypes
208 my $implType = shift;
211 my $svgListPropertyType;
214 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
216 $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
217 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
219 # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType>
220 $svgNativeType = "$svgNativeType ";
222 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
223 if ($svgNativeType =~ /SVGPropertyTearOff/) {
224 $svgPropertyType = $svgWrappedNativeType;
225 $implIncludes{"SVGAnimatedPropertyTearOff.h"} = 1;
226 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
227 $svgListPropertyType = $svgWrappedNativeType;
228 $implIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
231 $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint";
232 return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
238 my $dataNode = shift;
240 my $interfaceName = $dataNode->name;
241 my $className = "V8$interfaceName";
242 my $implClassName = $interfaceName;
244 # Copy contents of parent classes except the first parent or if it is
246 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
248 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
250 # - Add default header template
251 push(@headerContent, GenerateHeaderContentHeader($dataNode));
252 my $podType = $dataNode->extendedAttributes->{"PODType"};
254 my %headerInclues = ();
255 $headerIncludes{"$podType.h"} = 1 if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
256 $headerIncludes{"wtf/text/StringHash.h"} = 1;
257 $headerIncludes{"WrapperTypeInfo.h"} = 1;
258 $headerIncludes{"V8DOMWrapper.h"} = 1;
260 my $headerClassInclude = GetHeaderClassInclude($implClassName);
261 $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
263 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
265 foreach my $headerInclude (sort keys(%headerIncludes)) {
266 push(@headerContent, "#include \"${headerInclude}\"\n");
269 push(@headerContent, "#include <v8.h>\n");
270 push(@headerContent, "#include <wtf/HashMap.h>\n");
272 push(@headerContent, "\nnamespace WebCore {\n");
273 push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n") if $podType;
274 push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
276 push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n") if $svgListPropertyType;
278 if ($svgListPropertyType) {
279 if ($svgListPropertyType =~ /SVGStaticListPropertyTearOff/) {
280 push(@headerContent, "\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
282 push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
285 >>>>>>> webkit.org at r71558
286 push(@headerContent, "\nclass FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect";
287 push(@headerContent, "\nclass $className {\n");
289 my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
290 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
291 my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
292 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
293 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
295 push(@headerContent, <<END);
298 static bool HasInstance(v8::Handle<v8::Value> value);
299 static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
300 static v8::Persistent<v8::FunctionTemplate> GetTemplate();
301 static ${nativeType}* toNative(v8::Handle<v8::Object> object)
303 return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
305 inline static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
306 static void derefObject(void*);
307 static WrapperTypeInfo info;
309 if (IsActiveDomType($implClassName)) {
310 push(@headerContent, " static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
313 if ($implClassName eq "DOMWindow") {
314 push(@headerContent, <<END);
315 static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
319 if ($implClassName eq "HTMLDocument") {
320 push(@headerContent, <<END);
321 static v8::Local<v8::Object> WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl);
322 static v8::Handle<v8::Value> GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key);
326 my @enabledAtRuntime;
327 foreach my $function (@{$dataNode->functions}) {
328 my $name = $function->signature->name;
329 my $attrExt = $function->signature->extendedAttributes;
331 if ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
332 push(@headerContent, <<END);
333 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
337 if ($attrExt->{"EnabledAtRuntime"}) {
338 push(@enabledAtRuntime, $function);
342 if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
343 push(@headerContent, <<END);
344 static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args);
348 foreach my $attribute (@{$dataNode->attributes}) {
349 my $name = $attribute->signature->name;
350 my $attrExt = $attribute->signature->extendedAttributes;
351 if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"}
352 || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
353 push(@headerContent, <<END);
354 static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
357 if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"}
358 || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
359 push(@headerContent, <<END);
360 static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
363 if ($attrExt->{"EnabledAtRuntime"}) {
364 push(@enabledAtRuntime, $attribute);
368 GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
369 GenerateHeaderCustomCall($dataNode);
370 GenerateHeaderCustomInternalFieldIndices($dataNode);
372 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
373 push(@headerContent, <<END);
374 static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
375 static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
379 push(@headerContent, <<END);
381 static v8::Handle<v8::Object> wrapSlow(${nativeType}*);
386 push(@headerContent, <<END);
388 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput})
391 if ($domMapFunction) {
392 push(@headerContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
393 my $getWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getWrapper(impl)" : "${domMapFunction}.get(impl)";
394 push(@headerContent, <<END);
395 v8::Handle<v8::Object> wrapper = ${getWrapper};
396 if (!wrapper.IsEmpty())
399 push(@headerContent, " }\n") if IsDOMNodeType($interfaceName);
401 push(@headerContent, <<END);
402 return ${className}::wrapSlow(impl);
406 if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
407 push(@headerContent, <<END);
409 inline v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectParameter})
413 return ${className}::wrap(impl${forceNewObjectCall});
416 } elsif ($interfaceName ne 'Node') {
417 push(@headerContent, <<END);
419 v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
422 push(@headerContent, <<END);
424 v8::Handle<v8::Value> toV8Slow(Node*, bool);
426 inline v8::Handle<v8::Value> toV8(Node* impl, bool forceNewObject = false)
430 if (!forceNewObject) {
431 v8::Handle<v8::Value> wrapper = V8DOMWrapper::getWrapper(impl);
432 if (!wrapper.IsEmpty())
435 return toV8Slow(impl, forceNewObject);
440 if (IsRefPtrType($implClassName)) {
441 push(@headerContent, <<END);
442 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl${forceNewObjectParameter})
444 return toV8(impl.get()${forceNewObjectCall});
449 push(@headerContent, "}\n\n");
450 push(@headerContent, "#endif // $className" . "_h\n");
452 my $conditionalString = GenerateConditionalString($dataNode);
453 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
456 sub GetInternalFields
458 my $dataNode = shift;
459 my $name = $dataNode->name;
461 my @customInternalFields = ();
463 # We can't ask whether a parent type has a given extendedAttribute, so special-case Node, AbstractWorker and WorkerContext to include all sub-types.
464 # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't.
465 if ($dataNode->extendedAttributes->{"EventTarget"} || IsNodeSubType($dataNode) || IsSubType($dataNode, "AbstractWorker") || IsSubType($dataNode, "WorkerContext")
466 || $name eq "SVGElementInstance") {
467 push(@customInternalFields, "eventListenerCacheIndex");
470 if (IsSubType($dataNode, "Document")) {
471 push(@customInternalFields, "implementationIndex");
472 } elsif ($name eq "DOMWindow") {
473 push(@customInternalFields, "enteredIsolatedWorldIndex");
475 return @customInternalFields;
478 sub GetHeaderClassInclude
480 my $className = shift;
481 if ($className =~ /SVGPathSeg/) {
482 $className =~ s/Abs|Rel//;
484 return "" if ($codeGenerator->AvoidInclusionOfType($className));
485 return "DeprecatedSVGAnimatedTemplate.h" if $codeGenerator->IsSVGAnimatedType($className) and !$codeGenerator->IsSVGNewStyleAnimatedType($className);
486 return "${className}.h";
489 sub GenerateHeaderCustomInternalFieldIndices
491 my $dataNode = shift;
492 my @customInternalFields = GetInternalFields($dataNode);
493 my $customFieldCounter = 0;
494 foreach my $customInternalField (@customInternalFields) {
495 push(@headerContent, <<END);
496 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
498 $customFieldCounter++;
500 push(@headerContent, <<END);
501 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
505 my %indexerSpecialCases = (
507 "HTMLAppletElement" => 1,
508 "HTMLEmbedElement" => 1,
509 "HTMLObjectElement" => 1
512 sub GenerateHeaderNamedAndIndexedPropertyAccessors
514 my $dataNode = shift;
515 my $interfaceName = $dataNode->name;
516 my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
517 my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
518 my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
519 my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
520 my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
521 my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
522 if ($interfaceName eq "HTMLOptionsCollection") {
523 $interfaceName = "HTMLCollection";
524 $hasCustomIndexedGetter = 1;
525 $hasCustomNamedGetter = 1;
527 if ($interfaceName eq "DOMWindow") {
528 $hasCustomDeleterr = 0;
531 if ($interfaceName eq "HTMLSelectElement" || $interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
532 $hasCustomNamedGetter = 1;
534 if ($interfaceName eq "HTMLDocument") {
535 $hasCustomNamedGetter = 0;
536 $hasCustomIndexedGetter = 0;
538 my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
540 if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
541 push(@headerContent, <<END);
542 static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
546 if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
547 push(@headerContent, <<END);
548 static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
551 if ($hasCustomDeleters) {
552 push(@headerContent, <<END);
553 static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
556 if ($hasCustomNamedGetter) {
557 push(@headerContent, <<END);
558 static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
561 if ($hasCustomNamedSetter) {
562 push(@headerContent, <<END);
563 static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
566 if ($hasCustomDeleters) {
567 push(@headerContent, <<END);
568 static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
571 if ($hasCustomEnumerator) {
572 push(@headerContent, <<END);
573 static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
574 static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
579 sub GenerateHeaderCustomCall
581 my $dataNode = shift;
583 if ($dataNode->extendedAttributes->{"CustomCall"}) {
584 push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
586 if ($dataNode->name eq "Event") {
587 push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
588 push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n");
590 if ($dataNode->name eq "Location") {
591 push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
592 push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
593 push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
597 sub GenerateSetDOMException
602 $result .= $indent . "if (UNLIKELY(ec)) {\n";
603 $result .= $indent . " V8Proxy::setDOMException(ec);\n";
604 $result .= $indent . " return v8::Handle<v8::Value>();\n";
605 $result .= $indent . "}\n";
612 my $dataNode = shift;
613 my $parentType = shift;
614 return 1 if ($dataNode->name eq $parentType);
615 foreach (@allParents) {
616 my $parent = $codeGenerator->StripModule($_);
617 return 1 if $parent eq $parentType;
624 my $dataNode = shift;
625 return IsSubType($dataNode, "Node");
628 sub GenerateDomainSafeFunctionGetter
630 my $function = shift;
631 my $implClassName = shift;
633 my $className = "V8" . $implClassName;
634 my $funcName = $function->signature->name;
636 my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
637 if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
638 $signature = "v8::Local<v8::Signature>()";
641 my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature);
643 push(@implContentDecls, <<END);
644 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
646 INC_STATS(\"DOM.$implClassName.$funcName._get\");
647 static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
648 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
649 if (holder.IsEmpty()) {
650 // can only reach here by 'object.__proto__.func', and it should passed
651 // domain security check already
652 return privateTemplate->GetFunction();
654 ${implClassName}* imp = ${className}::toNative(holder);
655 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
656 static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
657 return sharedTemplate->GetFunction();
659 return privateTemplate->GetFunction();
665 sub GenerateConstructorGetter
667 my $implClassName = shift;
669 push(@implContentDecls, <<END);
670 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
672 INC_STATS(\"DOM.$implClassName.constructors._get\");
673 v8::Handle<v8::Value> data = info.Data();
674 ASSERT(data->IsExternal() || data->IsNumber());
675 WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data);
678 if ($implClassName eq "DOMWindow") {
679 push(@implContentDecls, <<END);
680 // Get the proxy corresponding to the DOMWindow if possible to
681 // make sure that the constructor function is constructed in the
682 // context of the DOMWindow and not in the context of the caller.
683 return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder()));
685 } elsif ($implClassName eq "DedicatedWorkerContext" or $implClassName eq "WorkerContext" or $implClassName eq "SharedWorkerContext") {
686 push(@implContentDecls, <<END);
687 return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder()));
690 push(@implContentDecls, " return v8::Handle<v8::Value>();");
693 push(@implContentDecls, <<END);
699 sub GenerateNormalAttrGetter
701 my $attribute = shift;
702 my $dataNode = shift;
703 my $implClassName = shift;
704 my $interfaceName = shift;
706 my $attrExt = $attribute->signature->extendedAttributes;
708 my $attrName = $attribute->signature->name;
710 my $attrType = GetTypeFromSignature($attribute->signature);
711 my $attrIsPodType = IsPodType($attrType);
713 my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
714 my $isPodType = IsPodType($implClassName);
718 $implClassName = GetNativeType($implClassName);
719 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
722 # Special case: SVGZoomEvent's attributes are all read-only
723 if ($implClassName eq "SVGZoomEvent") {
728 # Special case for SVGColor
729 if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) {
733 my $getterStringUsesImp = $implClassName ne "SVGNumber";
734 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
737 my $conditionalString = GenerateConditionalString($attribute->signature);
738 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
740 push(@implContentDecls, <<END);
741 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
743 INC_STATS(\"DOM.$implClassName.$attrName._get\");
747 push(@implContentDecls, <<END);
748 V8SVGPODTypeWrapper<$implClassName>* impWrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());
749 $implClassName impInstance = *impWrapper;
751 if ($getterStringUsesImp) {
752 push(@implContentDecls, <<END);
753 $implClassName* imp = &impInstance;
756 } elsif ($svgNativeType) {
757 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
758 if ($svgWrappedNativeType =~ /List$/) {
759 push(@implContentDecls, <<END);
760 $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
763 push(@implContentDecls, <<END);
764 $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());
765 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
767 if ($getterStringUsesImp) {
768 push(@implContentDecls, <<END);
769 $svgWrappedNativeType* imp = &impInstance;
773 } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
774 if ($interfaceName eq "DOMWindow") {
775 push(@implContentDecls, <<END);
776 v8::Handle<v8::Object> holder = info.Holder();
779 # perform lookup first
780 push(@implContentDecls, <<END);
781 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
782 if (holder.IsEmpty())
783 return v8::Handle<v8::Value>();
786 push(@implContentDecls, <<END);
787 ${implClassName}* imp = V8${implClassName}::toNative(holder);
790 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
791 my $url = $attribute->signature->extendedAttributes->{"URL"};
792 if ($getterStringUsesImp && $reflect && !$url && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
793 # Generate super-compact call for regular attribute getter:
794 my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect;
795 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
796 $implIncludes{"${namespace}.h"} = 1;
797 push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
798 push(@implContentDecls, "}\n\n");
799 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
801 # Skip the rest of the function!
803 push(@implContentDecls, <<END);
804 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
808 # Generate security checks if necessary
809 if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
810 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName()))\n return v8::Handle<v8::Value>();\n\n");
811 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
812 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument()))\n return v8::Handle<v8::Value>();\n\n");
815 my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
816 if ($useExceptions) {
817 $implIncludes{"ExceptionCode.h"} = 1;
818 push(@implContentDecls, " ExceptionCode ec = 0;\n");
821 if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
822 $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
825 my $returnType = GetTypeFromSignature($attribute->signature);
828 if ($getterStringUsesImp) {
829 $getterString = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
830 $getterString .= "ec" if $useExceptions;
831 $getterString .= ")";
833 $getterString = "impInstance";
839 if ($attrIsPodType) {
840 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
842 my $getter = $getterString;
843 $getter =~ s/imp->//;
845 my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
847 my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
848 if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
849 if (IsPodType($implClassName)) {
850 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, impWrapper)";
851 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
853 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
854 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
857 if ($implClassIsAnimatedType) {
858 # We can't hash member function pointers, so instead generate
859 # some hashing material based on the names of the methods.
860 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
861 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
862 push(@implContentDecls, " RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
864 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
865 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
870 if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
871 push(@implContentDecls, " if (!imp->document())\n");
872 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
875 if ($useExceptions) {
876 if ($nativeType =~ /^V8Parameter/) {
877 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $getterString) . ";\n");
879 push(@implContentDecls, " $nativeType v = $getterString;\n");
881 push(@implContentDecls, GenerateSetDOMException(" "));
883 $result .= ".release()" if (IsRefPtrType($returnType));
885 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
886 $result = $getterString;
889 # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
890 # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
891 # the newly created wrapper into an internal field of the holder object.
892 if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"})
893 && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow"
894 && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) {
895 AddIncludesForType($returnType);
896 my $domMapFunction = GetDomMapFunction(0, $returnType);
897 # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
898 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
899 push(@implContentDecls, " RefPtr<$returnType> result = ${getterString};\n");
900 push(@implContentDecls, " v8::Handle<v8::Value> wrapper = result.get() ? ${domMapFunction}.get(result.get()) : v8::Handle<v8::Value>();\n");
901 push(@implContentDecls, " if (wrapper.IsEmpty()) {\n");
902 push(@implContentDecls, " wrapper = toV8(result.get());\n");
903 push(@implContentDecls, " if (!wrapper.IsEmpty())\n");
904 if ($dataNode->name eq "DOMWindow") {
905 push(@implContentDecls, " V8DOMWrapper::setHiddenWindowReference(imp->frame(), wrapper);\n");
907 push(@implContentDecls, " V8DOMWrapper::setHiddenReference(info.Holder(), wrapper);\n");
909 push(@implContentDecls, " }\n");
910 push(@implContentDecls, " return wrapper;\n");
911 push(@implContentDecls, "}\n\n");
912 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
917 if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
918 if ($attrIsPodType) {
919 push(@implContentDecls, GenerateSVGContextAssignment($implClassName, "wrapper.get()", " "));
921 push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, " "));
922 # The templating associated with passing withSVGContext()'s return value directly into toV8 can get compilers confused,
923 # so just manually set the return value to a PassRefPtr of the expected type.
924 push(@implContentDecls, " PassRefPtr<$attrType> resultAsPassRefPtr = V8Proxy::withSVGContext($result, context);\n");
925 $result = "resultAsPassRefPtr";
929 if ($codeGenerator->IsSVGNewStyleAnimatedType($implClassName) and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) {
930 $implIncludes{"V8$attrType.h"} = 1;
931 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
932 # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
933 push(@implContentDecls, " return toV8(static_cast<$svgNativeType*>($result));\n");
934 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $implClassName =~ /List$/) {
935 $implIncludes{"V8$attrType.h"} = 1;
936 $implIncludes{"SVGPropertyTearOff.h"} = 1;
938 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
939 push(@implContentDecls, " return toV8(WTF::getPtr(${svgNativeType}::create($result)));\n");
941 my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
942 if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
943 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
944 $implIncludes{"SVGStaticPropertyTearOff.h"} = 1;
946 my $getter = $result;
947 $getter =~ s/imp->//;
949 my $updater = "update" . $codeGenerator->WK_ucfirst($getter);
950 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(imp, $result, &${implClassName}::$updater)));\n");
951 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
952 my $extraImp = "GetOwnerElementForType<$implClassName, IsDerivedFromSVGElement<$implClassName>::value>::ownerElement(imp), ";
953 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create($extraImp$result)));\n");
954 } elsif ($tearOffType =~ /SVGPointList/) {
955 push(@implContentDecls, " return toV8(WTF::getPtr($result));\n");
957 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create($result)));\n");
959 >>>>>>> webkit.org at r71558
960 } elsif ($attrIsPodType) {
961 $implIncludes{"V8${attrType}.h"} = 1;
962 push(@implContentDecls, " return toV8(wrapper.release().get());\n");
964 push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n");
967 push(@implContentDecls, "}\n\n"); # end of getter
968 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
971 sub GenerateNormalAttrSetter
973 my $attribute = shift;
974 my $dataNode = shift;
975 my $implClassName = shift;
976 my $interfaceName = shift;
978 $implIncludes{"V8BindingMacros.h"} = 1;
980 my $attrExt = $attribute->signature->extendedAttributes;
982 my $conditionalString = GenerateConditionalString($attribute->signature);
983 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
985 push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
986 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
988 # For functions with "StrictTypeChecking", if an input parameter's type does not match the signature,
989 # a TypeError is thrown instead of casting to null.
990 if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
991 my $argType = GetTypeFromSignature($attribute->signature);
992 if (IsWrapperType($argType)) {
993 push(@implContentDecls, " if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value)) {\n");
994 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
995 push(@implContentDecls, " return;\n");
996 push(@implContentDecls, " }\n");
997 } elsif ($codeGenerator->IsStringType($argType)) {
998 push(@implContentDecls, " if (!isUndefinedOrNull(value) && !value->IsString() && !value->IsObject()) {\n");
999 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1000 push(@implContentDecls, " return;\n");
1001 push(@implContentDecls, " }\n");
1002 } elsif ($codeGenerator->IsNumericType($argType)) {
1003 push(@implContentDecls, " if (!isUndefinedOrNull(value) && !value->IsNumber() && !value->IsBoolean()) {\n");
1004 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1005 push(@implContentDecls, " return;\n");
1006 push(@implContentDecls, " }\n");
1007 } elsif ($argType eq "boolean") {
1008 push(@implContentDecls, " if (!isUndefinedOrNull(value) && !value->IsBoolean()) {\n");
1009 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1010 push(@implContentDecls, " return;\n");
1011 push(@implContentDecls, " }\n");
1015 my $isPodType = IsPodType($implClassName);
1016 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
1019 $implClassName = GetNativeType($implClassName);
1020 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
1021 push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n");
1022 push(@implContentDecls, " $implClassName impInstance = *wrapper;\n");
1023 push(@implContentDecls, " $implClassName* imp = &impInstance;\n");
1024 } elsif ($svgNativeType) {
1025 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1026 if ($svgWrappedNativeType =~ /List$/) {
1027 push(@implContentDecls, <<END);
1028 $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
1031 push(@implContentDecls, <<END);
1032 $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());
1033 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
1034 $svgWrappedNativeType* imp = &impInstance;
1037 } elsif ($attrExt->{"v8OnProto"}) {
1038 if ($interfaceName eq "DOMWindow") {
1039 push(@implContentDecls, <<END);
1040 v8::Handle<v8::Object> holder = info.Holder();
1043 # perform lookup first
1044 push(@implContentDecls, <<END);
1045 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
1046 if (holder.IsEmpty())
1050 push(@implContentDecls, <<END);
1051 ${implClassName}* imp = V8${implClassName}::toNative(holder);
1054 my $attrType = GetTypeFromSignature($attribute->signature);
1055 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1056 if ($reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
1057 # Generate super-compact call for regular attribute setter:
1058 my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect;
1059 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1060 $implIncludes{"${namespace}.h"} = 1;
1061 push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
1062 push(@implContentDecls, "}\n\n");
1063 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1065 # Skip the rest of the function!
1068 push(@implContentDecls, <<END);
1069 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
1073 my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
1074 if ($attribute->signature->type eq "EventListener") {
1075 if ($dataNode->name eq "DOMWindow") {
1076 push(@implContentDecls, " if (!imp->document())\n");
1077 push(@implContentDecls, " return;\n");
1080 my $value = JSValueToNative($attribute->signature, "value");
1081 if ($nativeType =~ /^V8Parameter/) {
1082 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
1084 push(@implContentDecls, " $nativeType v = $value;\n");
1089 my $returnType = GetTypeFromSignature($attribute->signature);
1090 if (IsRefPtrType($returnType)) {
1091 $result = "WTF::getPtr(" . $result . ")";
1094 my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
1096 if ($useExceptions) {
1097 $implIncludes{"ExceptionCode.h"} = 1;
1098 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1101 if ($implClassName eq "SVGNumber") {
1102 push(@implContentDecls, " *imp = $result;\n");
1104 if ($attribute->signature->type eq "EventListener") {
1105 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
1106 $implIncludes{"V8AbstractEventListener.h"} = 1;
1107 push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n");
1108 if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
1109 $implIncludes{"V8EventListenerList.h"} = 1;
1110 $implIncludes{"V8WorkerContextErrorHandler.h"} = 1;
1111 push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
1113 push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)");
1116 my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
1117 push(@implContentDecls, " imp->$setterExpressionPrefix$result");
1119 push(@implContentDecls, ", ec") if $useExceptions;
1120 push(@implContentDecls, ");\n");
1123 if ($useExceptions) {
1124 push(@implContentDecls, " if (UNLIKELY(ec))\n");
1125 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
1129 push(@implContentDecls, " wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
1130 } elsif ($svgNativeType) {
1131 if ($useExceptions) {
1132 push(@implContentDecls, " if (!ec)\n");
1133 push(@implContentDecls, " wrapper->commitChange();\n");
1135 push(@implContentDecls, " wrapper->commitChange();\n");
1137 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
1138 $implIncludes{"SVGElement.h"} = 1;
1140 my $currentObject = "imp";
1142 $currentObject = "wrapper";
1145 push(@implContentDecls, " if (SVGElement* context = V8Proxy::svgContext($currentObject))\n");
1146 push(@implContentDecls, " context->svgAttributeChanged(imp->associatedAttributeName());\n");
1149 push(@implContentDecls, " return;\n");
1150 push(@implContentDecls, "}\n\n"); # end of setter
1151 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1154 sub GetFunctionTemplateCallbackName
1157 $interfaceName = shift;
1159 my $name = $function->signature->name;
1161 if ($function->signature->extendedAttributes->{"Custom"} ||
1162 $function->signature->extendedAttributes->{"V8Custom"}) {
1163 if ($function->signature->extendedAttributes->{"Custom"} &&
1164 $function->signature->extendedAttributes->{"V8Custom"}) {
1165 die "Custom and V8Custom should be mutually exclusive!"
1167 return "V8${interfaceName}::${name}Callback";
1169 return "${interfaceName}Internal::${name}Callback";
1173 sub GenerateNewFunctionTemplate
1176 $interfaceName = shift;
1179 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1180 return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
1183 sub GenerateEventListenerCallback
1185 my $implClassName = shift;
1186 my $functionName = shift;
1187 my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
1188 my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1189 my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1191 push(@implContentDecls, <<END);
1192 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1194 INC_STATS("DOM.${implClassName}.${functionName}EventListener()");
1195 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType});
1197 V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue());
1198 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex);
1200 return v8::Undefined();
1206 sub GenerateParametersCheckExpression
1208 my $numParameters = shift;
1209 my $function = shift;
1211 my @andExpression = ();
1212 push(@andExpression, "args.Length() == $numParameters");
1213 my $parameterIndex = 0;
1214 foreach $parameter (@{$function->parameters}) {
1215 last if $parameterIndex >= $numParameters;
1216 my $value = "args[$parameterIndex]";
1217 my $type = GetTypeFromSignature($parameter);
1219 # Only DOMString or wrapper types are checked.
1220 # For DOMString, Null, Undefined and any Object are accepted too, as
1221 # these are acceptable values for a DOMString argument (any Object can
1222 # be converted to a string via .toString).
1223 if ($codeGenerator->IsStringType($type)) {
1224 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
1225 } elsif ($parameter->extendedAttributes->{"Callback"}) {
1226 # For Callbacks only checks if the value is null or object.
1227 push(@andExpression, "(${value}->IsNull() || ${value}->IsObject())");
1228 } elsif (IsWrapperType($type)) {
1229 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))");
1234 my $res = join(" && ", @andExpression);
1235 $res = "($res)" if @andExpression > 1;
1239 sub GenerateFunctionParametersCheck
1241 my $function = shift;
1243 my @orExpression = ();
1244 my $numParameters = 0;
1245 foreach $parameter (@{$function->parameters}) {
1246 if ($parameter->extendedAttributes->{"Optional"}) {
1247 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1251 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1252 return join(" || ", @orExpression);
1255 sub GenerateOverloadedFunctionCallback
1257 my $function = shift;
1258 my $dataNode = shift;
1259 my $implClassName = shift;
1261 # Generate code for choosing the correct overload to call. Overloads are
1262 # chosen based on the total number of arguments passed and the type of
1263 # values passed in non-primitive argument slots. When more than a single
1264 # overload is applicable, precedence is given according to the order of
1265 # declaration in the IDL.
1267 my $name = $function->signature->name;
1268 push(@implContentDecls, <<END);
1269 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1271 INC_STATS(\"DOM.$implClassName.$name\");
1274 foreach my $overload (@{$function->{overloads}}) {
1275 my $parametersCheck = GenerateFunctionParametersCheck($overload);
1276 push(@implContentDecls, " if ($parametersCheck)\n");
1277 push(@implContentDecls, " return ${name}$overload->{overloadIndex}Callback(args);\n");
1279 push(@implContentDecls, <<END);
1280 V8Proxy::throwTypeError();
1281 return notHandledByInterceptor();
1283 push(@implContentDecls, "}\n\n");
1286 sub GenerateFunctionCallback
1288 my $function = shift;
1289 my $dataNode = shift;
1290 my $implClassName = shift;
1292 my $interfaceName = $dataNode->name;
1293 my $name = $function->signature->name;
1295 if (@{$function->{overloads}} > 1) {
1296 # Append a number to an overloaded method's name to make it unique:
1297 $name = $name . $function->{overloadIndex};
1300 # Adding and removing event listeners are not standard callback behavior,
1301 # but they are extremely consistent across the various classes that take event listeners,
1302 # so we can generate them as a "special case".
1303 if ($name eq "addEventListener") {
1304 GenerateEventListenerCallback($implClassName, "add");
1306 } elsif ($name eq "removeEventListener") {
1307 GenerateEventListenerCallback($implClassName, "remove");
1311 push(@implContentDecls, <<END);
1312 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1314 INC_STATS(\"DOM.$implClassName.$name\");
1317 my $numParameters = @{$function->parameters};
1319 my $requiresAllArguments = $function->signature->extendedAttributes->{"RequiresAllArguments"};
1320 if ($requiresAllArguments) {
1321 my $numMandatoryParams = @{$function->parameters};
1322 foreach my $param (reverse(@{$function->parameters})) {
1323 if ($param->extendedAttributes->{"Optional"}) {
1324 $numMandatoryParams--;
1329 push(@implContentDecls, " if (args.Length() < $numMandatoryParams)\n");
1330 if ($requiresAllArguments eq "Raise") {
1331 push(@implContentDecls, " return throwError(\"Not enough arguments\", V8Proxy::SyntaxError);\n");
1333 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1337 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
1339 if (IsPodType($implClassName)) {
1340 my $nativeClassName = GetNativeType($implClassName);
1341 push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* impWrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n");
1342 push(@implContentDecls, " $nativeClassName impInstance = *impWrapper;\n");
1343 push(@implContentDecls, " $nativeClassName* imp = &impInstance;\n");
1344 } elsif ($svgNativeType) {
1345 my $nativeClassName = GetNativeType($implClassName);
1346 if ($implClassName =~ /List$/) {
1347 push(@implContentDecls, " $nativeClassName imp = V8${svgListPropertyType}::toNative(args.Holder());\n");
1349 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1350 push(@implContentDecls, " $nativeClassName wrapper = V8${svgPropertyType}::toNative(args.Holder());\n");
1351 push(@implContentDecls, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1352 push(@implContentDecls, " $svgWrappedNativeType* imp = &impInstance;\n");
1354 } elsif (!$function->signature->extendedAttributes->{"ClassMethod"}) {
1355 push(@implContentDecls, <<END);
1356 ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
1360 # Check domain security if needed
1361 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
1362 || $interfaceName eq "DOMWindow")
1363 && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1364 # We have not find real use cases yet.
1365 push(@implContentDecls, <<END);
1366 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
1367 return v8::Handle<v8::Value>();
1371 my $raisesExceptions = @{$function->raisesExceptions};
1372 if (!$raisesExceptions) {
1373 foreach my $parameter (@{$function->parameters}) {
1374 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1375 $raisesExceptions = 1;
1380 if ($raisesExceptions) {
1381 $implIncludes{"ExceptionCode.h"} = 1;
1382 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1383 push(@implContentDecls, " {\n");
1384 # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1385 # of objects (like Strings) declared later, causing compile errors. The block scope ends
1386 # right before the label 'fail:'.
1389 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1390 push(@implContentDecls, <<END);
1391 OwnPtr<ScriptArguments> scriptArguments(createScriptArguments(args, $numParameters));
1392 size_t maxStackSize = imp->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1;
1393 OwnPtr<ScriptCallStack> callStack(createScriptCallStack(maxStackSize));
1395 return v8::Undefined();
1397 $implIncludes{"ScriptArguments.h"} = 1;
1398 $implIncludes{"ScriptCallStack.h"} = 1;
1399 $implIncludes{"ScriptCallStackFactory.h"} = 1;
1401 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1402 push(@implContentDecls, <<END);
1403 if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))
1404 return v8::Handle<v8::Value>();
1409 foreach my $parameter (@{$function->parameters}) {
1410 TranslateParameter($parameter);
1412 my $parameterName = $parameter->name;
1414 # Optional callbacks should be treated differently, because they always have a default value (0),
1415 # and we can reduce the number of overloaded functions that take a different number of parameters.
1416 if ($parameter->extendedAttributes->{"Optional"} && !$parameter->extendedAttributes->{"Callback"}) {
1417 # Generate early call if there are not enough parameters.
1418 push(@implContentDecls, " if (args.Length() <= $paramIndex) {\n");
1419 my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName);
1420 push(@implContentDecls, $functionCall);
1421 push(@implContentDecls, " }\n");
1424 if (BasicTypeCanFailConversion($parameter)) {
1425 push(@implContentDecls, " bool ${parameterName}Ok;\n");
1428 $implIncludes{"ExceptionCode.h"} = 1;
1429 my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1430 if ($parameter->extendedAttributes->{"Callback"}) {
1431 my $className = GetCallbackClassName($parameter->type);
1432 $implIncludes{"$className.h"} = 1;
1433 if ($parameter->extendedAttributes->{"Optional"}) {
1434 push(@implContentDecls, " RefPtr<" . $parameter->type . "> $parameterName;\n");
1435 push(@implContentDecls, " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n");
1436 push(@implContentDecls, " if (!args[$paramIndex]->IsObject())\n");
1437 push(@implContentDecls, " return throwError(TYPE_MISMATCH_ERR);\n");
1438 push(@implContentDecls, " $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n");
1439 push(@implContentDecls, " }\n");
1441 push(@implContentDecls, " if (args.Length() <= $paramIndex || !args[$paramIndex]->IsObject())\n");
1442 push(@implContentDecls, " return throwError(TYPE_MISMATCH_ERR);\n");
1443 push(@implContentDecls, " RefPtr<" . $parameter->type . "> $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n");
1445 } elsif ($parameter->type eq "SerializedScriptValue") {
1446 $implIncludes{"SerializedScriptValue.h"} = 1;
1447 push(@implContentDecls, " bool ${parameterName}DidThrow = false;\n");
1448 push(@implContentDecls, " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n");
1449 push(@implContentDecls, " if (${parameterName}DidThrow)\n");
1450 push(@implContentDecls, " return v8::Undefined();\n");
1451 } elsif (TypeCanFailConversion($parameter)) {
1452 push(@implContentDecls, " $nativeType $parameterName = " .
1453 JSValueToNative($parameter, "args[$paramIndex]", BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n");
1454 push(@implContentDecls, " if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n");
1455 push(@implContentDecls, " ec = TYPE_MISMATCH_ERR;\n");
1456 push(@implContentDecls, " goto fail;\n");
1457 push(@implContentDecls, " }\n");
1458 } elsif ($nativeType =~ /^V8Parameter/) {
1459 my $value = JSValueToNative($parameter, "args[$paramIndex]", BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef);
1460 push(@implContentDecls, " " . ConvertToV8Parameter($parameter, $nativeType, $parameterName, $value) . "\n");
1462 $implIncludes{"V8BindingMacros.h"} = 1;
1463 # For functions with "StrictTypeChecking", if an input parameter's type does not match the signature,
1464 # a TypeError is thrown instead of casting to null.
1465 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1466 my $argValue = "args[$paramIndex]";
1467 my $argType = GetTypeFromSignature($parameter);
1468 if (IsWrapperType($argType)) {
1469 push(@implContentDecls, " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue)) {\n");
1470 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1471 push(@implContentDecls, " return notHandledByInterceptor();\n");
1472 push(@implContentDecls, " }\n");
1473 } elsif ($codeGenerator->IsStringType($argType)) {
1474 push(@implContentDecls, " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !${argValue}->IsString() && !${argValue}->IsObject()) {\n");
1475 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1476 push(@implContentDecls, " return notHandledByInterceptor();\n");
1477 push(@implContentDecls, " }\n");
1478 } elsif ($codeGenerator->IsNumericType($argType)) {
1479 push(@implContentDecls, " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !${argValue}->IsNumber() && !${argValue}->IsBoolean()) {\n");
1480 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1481 push(@implContentDecls, " return notHandledByInterceptor();\n");
1482 push(@implContentDecls, " }\n");
1485 push(@implContentDecls, " EXCEPTION_BLOCK($nativeType, $parameterName, " .
1486 JSValueToNative($parameter, "args[$paramIndex]", BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ");\n");
1489 if ($parameter->extendedAttributes->{"IsIndex"}) {
1490 push(@implContentDecls, " if (UNLIKELY($parameterName < 0)) {\n");
1491 push(@implContentDecls, " ec = INDEX_SIZE_ERR;\n");
1492 push(@implContentDecls, " goto fail;\n");
1493 push(@implContentDecls, " }\n");
1499 # Build the function call string.
1500 my $callString = GenerateFunctionCallString($function, $paramIndex, " ", $implClassName);
1501 push(@implContentDecls, "$callString");
1503 if ($raisesExceptions) {
1504 push(@implContentDecls, " }\n");
1505 push(@implContentDecls, " fail:\n");
1506 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
1507 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1510 push(@implContentDecls, "}\n\n");
1513 sub GenerateBatchedAttributeData
1515 my $dataNode = shift;
1516 my $interfaceName = $dataNode->name;
1517 my $attributes = shift;
1519 foreach my $attribute (@$attributes) {
1520 my $conditionalString = GenerateConditionalString($attribute->signature);
1521 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1522 GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1523 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
1527 sub GenerateSingleBatchedAttribute
1529 my $interfaceName = shift;
1530 my $attribute = shift;
1531 my $delimiter = shift;
1533 my $attrName = $attribute->signature->name;
1534 my $attrExt = $attribute->signature->extendedAttributes;
1536 # Attributes of type SerializedScriptValue are set in the
1537 # constructor and don't require callbacks.
1538 return if ($attribute->signature->type eq "SerializedScriptValue");
1540 my $accessControl = "v8::DEFAULT";
1541 if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1542 $accessControl = "v8::ALL_CAN_READ";
1543 } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1544 $accessControl = "v8::ALL_CAN_WRITE";
1545 } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1546 $accessControl = "v8::ALL_CAN_READ";
1547 if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1548 $accessControl .= " | v8::ALL_CAN_WRITE";
1551 if ($attrExt->{"V8DisallowShadowing"}) {
1552 $accessControl .= " | v8::PROHIBITS_OVERWRITING";
1554 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1556 my $customAccessor =
1557 $attrExt->{"Custom"} ||
1558 $attrExt->{"CustomSetter"} ||
1559 $attrExt->{"CustomGetter"} ||
1560 $attrExt->{"V8Custom"} ||
1561 $attrExt->{"V8CustomSetter"} ||
1562 $attrExt->{"V8CustomGetter"} ||
1564 if ($customAccessor eq 1) {
1565 # use the naming convension, interface + (capitalize) attr name
1566 $customAccessor = $interfaceName . "::" . $attrName;
1571 my $propAttr = "v8::None";
1572 my $hasCustomSetter = 0;
1575 if ($attrExt->{"DontEnum"}) {
1576 $propAttr .= " | v8::DontEnum";
1578 if ($attrExt->{"V8DisallowShadowing"}) {
1579 $propAttr .= " | v8::DontDelete";
1582 my $on_proto = "0 /* on instance */";
1583 my $data = "0 /* no data */";
1586 if ($attribute->signature->type =~ /Constructor$/) {
1587 my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1588 $constructorType =~ s/Constructor$//;
1589 $implIncludes{"V8${constructorType}.h"} = 1;
1590 if ($customAccessor) {
1591 $getter = "V8${customAccessor}AccessorGetter";
1593 $data = "&V8${constructorType}::info";
1594 $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1597 $propAttr = "v8::ReadOnly";
1600 # Default Getter and Setter
1601 $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1602 $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1605 if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1606 $hasCustomSetter = 1;
1607 $setter = "V8${customAccessor}AccessorSetter";
1611 if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1612 $getter = "V8${customAccessor}AccessorGetter";
1617 if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1619 # Handle the special case of window.top being marked as Replaceable.
1620 # FIXME: Investigate whether we could treat window.top as replaceable
1621 # and allow shadowing without it being a security hole.
1622 if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1623 $propAttr .= " | v8::ReadOnly";
1627 # Read only attributes
1628 if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1632 # An accessor can be installed on the proto
1633 if ($attrExt->{"v8OnProto"}) {
1634 $on_proto = "1 /* on proto */";
1637 my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1638 "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1640 push(@implContent, $indent . " \/\/ $commentInfo\n");
1641 push(@implContent, $indent . " {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
1644 sub GenerateImplementationIndexer
1646 my $dataNode = shift;
1647 my $indexer = shift;
1648 my $interfaceName = $dataNode->name;
1650 # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files.
1651 my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
1652 my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1654 # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
1655 if ($interfaceName eq "HTMLOptionsCollection") {
1658 # FIXME: If the parent interface of $dataNode already has
1659 # HasIndexGetter, we don't need to handle the getter here.
1660 if ($interfaceName eq "WebKitCSSTransformValue") {
1664 # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
1665 # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
1666 # simplistic, mirrored indexer handling in addition to named property handling.
1667 my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
1668 if ($isSpecialCase) {
1670 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
1671 $hasCustomSetter = 1;
1679 $implIncludes{"V8Collection.h"} = 1;
1681 my $indexerType = $indexer ? $indexer->type : 0;
1683 # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
1684 if ($interfaceName eq "WebKitCSSKeyframesRule") {
1685 $indexerType = "WebKitCSSKeyframeRule";
1688 if ($indexerType && !$hasCustomSetter) {
1689 if ($indexerType eq "DOMString") {
1690 my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
1691 if ($conversion && $conversion eq "Null") {
1692 push(@implContent, <<END);
1693 setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
1696 push(@implContent, <<END);
1697 setCollectionStringIndexedGetter<${interfaceName}>(desc);
1701 push(@implContent, <<END);
1702 setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
1704 # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
1705 $implIncludes{"V8${indexerType}.h"} = 1;
1711 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1712 my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
1713 my $setOn = "Instance";
1715 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1716 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1717 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1719 if ($interfaceName eq "DOMWindow") {
1720 $setOn = "Prototype";
1724 push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
1725 push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
1726 push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
1727 push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
1728 push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
1729 push(@implContent, ");\n");
1732 sub GenerateImplementationNamedPropertyGetter
1734 my $dataNode = shift;
1735 my $namedPropertyGetter = shift;
1736 my $interfaceName = $dataNode->name;
1737 my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1739 # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
1740 # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
1741 if ($interfaceName eq "HTMLOptionsCollection") {
1742 $interfaceName = "HTMLCollection";
1743 $hasCustomGetter = 1;
1746 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
1747 $hasCustomGetter = 1;
1750 if ($interfaceName eq "HTMLDocument") {
1751 $hasCustomGetter = 0;
1754 my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter;
1759 if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) {
1760 $implIncludes{"V8Collection.h"} = 1;
1761 my $type = $namedPropertyGetter->type;
1762 push(@implContent, <<END);
1763 setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
1768 my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
1769 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1770 my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
1771 my $setOn = "Instance";
1773 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1774 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1775 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1777 if ($interfaceName eq "DOMWindow") {
1778 $setOn = "Prototype";
1783 push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
1784 push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
1785 # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
1786 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyQuery, " : "0, ");
1787 push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
1788 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
1789 push(@implContent, ");\n");
1792 sub GenerateImplementationCustomCall
1794 my $dataNode = shift;
1795 my $interfaceName = $dataNode->name;
1796 my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
1798 # FIXME: Remove hard-coded HTMLOptionsCollection reference.
1799 if ($interfaceName eq "HTMLOptionsCollection") {
1800 $interfaceName = "HTMLCollection";
1804 if ($hasCustomCall) {
1805 push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
1809 sub GenerateImplementationMasqueradesAsUndefined
1811 my $dataNode = shift;
1812 if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
1814 push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n");
1818 sub GenerateImplementation
1821 my $dataNode = shift;
1822 my $interfaceName = $dataNode->name;
1823 my $visibleInterfaceName = GetVisibleInterfaceName($interfaceName);
1824 my $className = "V8$interfaceName";
1825 my $implClassName = $interfaceName;
1827 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1829 # - Add default header template
1830 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
1832 $implIncludes{"RuntimeEnabledFeatures.h"} = 1;
1833 $implIncludes{"V8Proxy.h"} = 1;
1834 $implIncludes{"V8Binding.h"} = 1;
1835 $implIncludes{"V8BindingState.h"} = 1;
1836 $implIncludes{"V8DOMWrapper.h"} = 1;
1837 $implIncludes{"V8IsolatedContext.h"} = 1;
1839 if ($className =~ /^V8SVGAnimated/) {
1840 AddIncludesForSVGAnimatedType($interfaceName);
1843 AddIncludesForType($interfaceName);
1845 my $toActive = IsActiveDomType($interfaceName) ? "${className}::toActiveDOMObject" : "0";
1847 push(@implContentDecls, "namespace WebCore {\n\n");
1848 push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive} };\n\n");
1849 push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1850 push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1852 my $hasConstructors = 0;
1853 my $serializedAttribute;
1854 # Generate property accessors for attributes.
1855 for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1856 $attribute = @{$dataNode->attributes}[$index];
1857 $attrName = $attribute->signature->name;
1858 $attrType = $attribute->signature->type;
1860 # Generate special code for the constructor attributes.
1861 if ($attrType =~ /Constructor$/) {
1862 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1863 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1864 $hasConstructors = 1;
1869 if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1870 $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1873 # Attributes of type SerializedScriptValue are set in the
1874 # constructor and don't require callbacks.
1875 if ($attrType eq "SerializedScriptValue") {
1876 die "Only one attribute of type SerializedScriptValue supported" if $serializedAttribute;
1877 $implIncludes{"SerializedScriptValue.h"} = 1;
1878 $serializedAttribute = $attribute;
1882 # Do not generate accessor if this is a custom attribute. The
1883 # call will be forwarded to a hand-written accessor
1885 if ($attribute->signature->extendedAttributes->{"Custom"} ||
1886 $attribute->signature->extendedAttributes->{"V8Custom"}) {
1890 # Generate the accessor.
1891 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1892 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1893 GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
1895 if (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
1896 !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
1897 !$attribute->signature->extendedAttributes->{"Replaceable"} &&
1898 $attribute->type !~ /^readonly/ &&
1899 !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1900 GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
1904 if ($hasConstructors) {
1905 GenerateConstructorGetter($implClassName);
1908 $codeGenerator->LinkOverloadedFunctions($dataNode);
1911 my $namedPropertyGetter;
1912 # Generate methods for functions.
1913 foreach my $function (@{$dataNode->functions}) {
1914 if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) {
1915 GenerateFunctionCallback($function, $dataNode, $implClassName);
1916 if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
1917 GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName);
1921 if ($function->signature->name eq "item") {
1922 $indexer = $function->signature;
1925 if ($function->signature->name eq "namedItem") {
1926 $namedPropertyGetter = $function->signature;
1929 # If the function does not need domain security check, we need to
1930 # generate an access getter that returns different function objects
1931 # for different calling context.
1932 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1933 GenerateDomainSafeFunctionGetter($function, $implClassName);
1938 my $attributes = $dataNode->attributes;
1940 # For the DOMWindow interface we partition the attributes into the
1941 # ones that disallows shadowing and the rest.
1942 my @disallowsShadowing;
1943 # Also separate out attributes that are enabled at runtime so we can process them specially.
1944 my @enabledAtRuntime;
1946 foreach my $attribute (@$attributes) {
1948 if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1949 push(@disallowsShadowing, $attribute);
1950 } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1951 push(@enabledAtRuntime, $attribute);
1953 push(@normal, $attribute);
1956 $attributes = \@normal;
1957 # Put the attributes that disallow shadowing on the shadow object.
1958 if (@disallowsShadowing) {
1959 push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n");
1960 GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1961 push(@implContent, "};\n");
1964 my $has_attributes = 0;
1966 $has_attributes = 1;
1967 push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n");
1968 GenerateBatchedAttributeData($dataNode, $attributes);
1969 push(@implContent, "};\n");
1972 # Setup table of standard callback functions
1975 foreach my $function (@{$dataNode->functions}) {
1976 # Only one table entry is needed for overloaded methods:
1977 next if $function->{overloadIndex} > 1;
1979 my $attrExt = $function->signature->extendedAttributes;
1980 # Don't put any nonstandard functions into this table:
1981 if ($attrExt->{"V8OnInstance"}) {
1984 if ($attrExt->{"ClassMethod"}) {
1987 if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1990 if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1991 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1994 if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1997 if (!$has_callbacks) {
1999 push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n");
2001 my $name = $function->signature->name;
2002 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2003 push(@implContent, <<END);
2004 {"$name", $callback},
2008 push(@implContent, "};\n") if $has_callbacks;
2011 my $has_constants = 0;
2012 if (@{$dataNode->constants}) {
2014 push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n");
2016 foreach my $constant (@{$dataNode->constants}) {
2017 my $name = $constant->name;
2018 my $value = $constant->value;
2019 # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
2020 # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we
2021 # handled this here, and converted it to a -1 constant in the c++ output.
2022 push(@implContent, <<END);
2023 {"${name}", static_cast<signed int>($value)},
2026 if ($has_constants) {
2027 push(@implContent, "};\n");
2028 push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
2031 push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
2033 # In namespace WebCore, add generated implementation for 'CanBeConstructed'.
2034 if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"} && !$dataNode->extendedAttributes->{"V8CustomConstructor"}) {
2035 my $v8ConstructFunction;
2036 my $callWith = $dataNode->extendedAttributes->{"CallWith"};
2037 if ($callWith and $callWith eq "ScriptExecutionContext") {
2038 $v8ConstructFunction = "constructDOMObjectWithScriptExecutionContext";
2040 $v8ConstructFunction = "constructDOMObject";
2042 push(@implContent, <<END);
2043 v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args)
2045 INC_STATS("DOM.${interfaceName}.Contructor");
2046 return V8Proxy::${v8ConstructFunction}<$interfaceName>(args, &info);
2051 my $access_check = "";
2052 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
2053 $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));";
2056 # For the DOMWindow interface, generate the shadow object template
2057 # configuration method.
2058 if ($implClassName eq "DOMWindow") {
2059 push(@implContent, <<END);
2060 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
2062 batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, sizeof(shadowAttrs) / sizeof(*shadowAttrs));
2064 // Install a security handler with V8.
2065 templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info));
2066 templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2072 # find the super descriptor
2073 my $parentClassTemplate = "";
2074 foreach (@{$dataNode->parents}) {
2075 my $parent = $codeGenerator->StripModule($_);
2076 if ($parent eq "EventTarget") { next; }
2077 $implIncludes{"V8${parent}.h"} = 1;
2078 $parentClassTemplate = "V8" . $parent . "::GetTemplate()";
2081 if (!$parentClassTemplate) {
2082 $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
2085 # Generate the template configuration method
2086 push(@implContent, <<END);
2087 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc)
2089 v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount,
2091 # Set up our attributes if we have them
2092 if ($has_attributes) {
2093 push(@implContent, <<END);
2094 ${interfaceName}Attrs, sizeof(${interfaceName}Attrs) / sizeof(*${interfaceName}Attrs),
2097 push(@implContent, <<END);
2102 if ($has_callbacks) {
2103 push(@implContent, <<END);
2104 ${interfaceName}Callbacks, sizeof(${interfaceName}Callbacks) / sizeof(*${interfaceName}Callbacks));
2107 push(@implContent, <<END);
2112 if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
2113 push(@implContent, <<END);
2114 desc->SetCallHandler(V8${interfaceName}::constructorCallback);
2118 if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
2119 push(@implContent, <<END);
2120 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
2121 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
2125 push(@implContent, " $access_check\n");
2127 # Setup the enable-at-runtime attrs if we have them
2128 foreach my $runtime_attr (@enabledAtRuntime) {
2129 my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
2130 my $conditionalString = GenerateConditionalString($runtime_attr->signature);
2131 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2132 push(@implContent, " if (${enable_function}()) {\n");
2133 push(@implContent, " static const BatchedAttribute attrData =\\\n");
2134 GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " ");
2135 push(@implContent, <<END);
2136 configureAttribute(instance, proto, attrData);
2139 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2142 GenerateImplementationIndexer($dataNode, $indexer);
2143 GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
2144 GenerateImplementationCustomCall($dataNode);
2145 GenerateImplementationMasqueradesAsUndefined($dataNode);
2147 # Define our functions with Set() or SetAccessor()
2148 $total_functions = 0;
2149 foreach my $function (@{$dataNode->functions}) {
2150 # Only one accessor is needed for overloaded methods:
2151 next if $function->{overloadIndex} > 1;
2154 my $attrExt = $function->signature->extendedAttributes;
2155 my $name = $function->signature->name;
2157 my $property_attributes = "v8::DontDelete";
2158 if ($attrExt->{"DontEnum"}) {
2159 $property_attributes .= " | v8::DontEnum";
2161 if ($attrExt->{"V8ReadOnly"}) {
2162 $property_attributes .= " | v8::ReadOnly";
2165 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2167 my $template = "proto";
2168 if ($attrExt->{"V8OnInstance"}) {
2169 $template = "instance";
2171 if ($attrExt->{"ClassMethod"}) {
2175 my $conditional = "";
2176 if ($attrExt->{"EnabledAtRuntime"}) {
2177 # Only call Set()/SetAccessor() if this method should be enabled
2178 $enable_function = GetRuntimeEnableFunctionName($function->signature);
2179 $conditional = "if (${enable_function}())\n ";
2182 if ($attrExt->{"DoNotCheckDomainSecurity"} &&
2183 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
2184 # Mark the accessor as ReadOnly and set it on the proto object so
2185 # it can be shadowed. This is really a hack to make it work.
2186 # There are several sceneria to call into the accessor:
2187 # 1) from the same domain: "window.open":
2188 # the accessor finds the DOM wrapper in the proto chain;
2189 # 2) from the same domain: "window.__proto__.open":
2190 # the accessor will NOT find a DOM wrapper in the prototype chain
2191 # 3) from another domain: "window.open":
2192 # the access find the DOM wrapper in the prototype chain
2193 # "window.__proto__.open" from another domain will fail when
2194 # accessing '__proto__'
2196 # The solution is very hacky and fragile, it really needs to be replaced
2197 # by a better solution.
2198 $property_attributes .= " | v8::ReadOnly";
2199 push(@implContent, <<END);
2202 ${conditional}$template->SetAccessor(v8::String::New("$name"), ${interfaceName}Internal::${name}AttrGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
2208 my $signature = "defaultSignature";
2209 if ($attrExt->{"V8DoNotCheckSignature"} || $attrExt->{"ClassMethod"}) {
2210 $signature = "v8::Local<v8::Signature>()";
2213 if (RequiresCustomSignature($function)) {
2214 $signature = "${name}Signature";
2215 push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function));
2218 # Normal function call is a template
2219 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2221 if ($property_attributes eq "v8::DontDelete") {
2222 $property_attributes = "";
2224 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2227 if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2228 # Standard type of callback, already created in the batch, so skip it here.
2232 push(@implContent, <<END);
2233 ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);
2238 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
2240 if ($has_constants) {
2241 push(@implContent, <<END);
2242 batchConfigureConstants(desc, proto, ${interfaceName}Consts, sizeof(${interfaceName}Consts) / sizeof(*${interfaceName}Consts));
2247 if ($interfaceName eq "DOMWindow") {
2248 push(@implContent, <<END);
2250 proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2251 desc->SetHiddenPrototype(true);
2252 instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2253 // Set access check callbacks, but turned off initially.
2254 // When a context is detached from a frame, turn on the access check.
2255 // Turning on checks also invalidates inline caches of the object.
2256 instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false);
2259 if ($interfaceName eq "HTMLDocument") {
2260 push(@implContent, <<END);
2261 desc->SetHiddenPrototype(true);
2264 if ($interfaceName eq "Location") {
2265 push(@implContent, <<END);
2267 // For security reasons, these functions are on the instance instead
2268 // of on the prototype object to ensure that they cannot be overwritten.
2269 instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2270 instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2271 instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
2275 my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
2276 push(@implContent, <<END);
2278 // Custom toString template
2279 desc->Set(getToStringName(), getToStringTemplate());
2283 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate()
2285 static v8::Persistent<v8::FunctionTemplate> ${className}RawCache = createRawTemplate();
2286 return ${className}RawCache;
2289 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()\
2291 static v8::Persistent<v8::FunctionTemplate> ${className}Cache = Configure${className}Template(GetRawTemplate());
2292 return ${className}Cache;
2295 bool ${className}::HasInstance(v8::Handle<v8::Value> value)
2297 return GetRawTemplate()->HasInstance(value);
2302 if (IsActiveDomType($interfaceName)) {
2303 # MessagePort is handled like an active dom object even though it doesn't inherit
2304 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
2305 my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
2306 push(@implContent, <<END);
2307 ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object)
2309 return ${returnValue};
2314 if ($implClassName eq "DOMWindow") {
2315 push(@implContent, <<END);
2316 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
2318 static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
2319 if (V8DOMWindowShadowObjectCache.IsEmpty()) {
2320 V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
2321 ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
2323 return V8DOMWindowShadowObjectCache;
2328 GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType, $serializedAttribute);
2330 push(@implContent, <<END);
2332 void ${className}::derefObject(void* object)
2336 if (IsRefPtrType($interfaceName)) {
2337 push(@implContent, <<END);
2338 static_cast<${nativeType}*>(object)->deref();
2342 push(@implContent, <<END);
2345 } // namespace WebCore
2348 my $conditionalString = GenerateConditionalString($dataNode);
2349 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2351 # We've already added the header for this file in implFixedHeader, so remove
2352 # it from implIncludes to ensure we don't #include it twice.
2353 delete $implIncludes{"${className}.h"};
2356 sub GenerateHeaderContentHeader
2358 my $dataNode = shift;
2359 my $className = "V8" . $dataNode->name;
2360 my $conditionalString = GenerateConditionalString($dataNode);
2362 my @headerContentHeader = split("\r", $headerTemplate);
2364 push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
2365 push(@headerContentHeader, "\n#ifndef ${className}" . "_h");
2366 push(@headerContentHeader, "\n#define ${className}" . "_h\n\n");
2367 return @headerContentHeader;
2370 sub GenerateImplementationContentHeader
2372 my $dataNode = shift;
2373 my $className = "V8" . $dataNode->name;
2374 my $conditionalString = GenerateConditionalString($dataNode);
2376 my @implContentHeader = split("\r", $headerTemplate);
2378 push(@implContentHeader, "\n#include \"config.h\"\n");
2379 push(@implContentHeader, "#include \"${className}.h\"\n\n");
2380 push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
2381 return @implContentHeader;
2384 sub GenerateCallbackHeader
2387 my $dataNode = shift;
2389 my $interfaceName = $dataNode->name;
2390 my $className = "V8$interfaceName";
2393 # - Add default header template
2394 push(@headerContent, GenerateHeaderContentHeader($dataNode));
2396 my @unsortedIncludes = ();
2397 push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\"");
2398 push(@unsortedIncludes, "#include \"$interfaceName.h\"");
2399 push(@unsortedIncludes, "#include \"WorldContextHandle.h\"");
2400 push(@unsortedIncludes, "#include <v8.h>");
2401 push(@unsortedIncludes, "#include <wtf/Forward.h>");
2402 push(@headerContent, join("\n", sort @unsortedIncludes));
2404 push(@headerContent, "\n\nnamespace WebCore {\n\n");
2405 push(@headerContent, "class ScriptExecutionContext;\n\n");
2406 push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
2408 push(@headerContent, <<END);
2410 static PassRefPtr<${className}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
2412 ASSERT(value->IsObject());
2414 return adoptRef(new ${className}(value->ToObject(), context));
2417 virtual ~${className}();
2422 my $numFunctions = @{$dataNode->functions};
2423 if ($numFunctions > 0) {
2424 push(@headerContent, " // Functions\n");
2425 foreach my $function (@{$dataNode->functions}) {
2426 my @params = @{$function->parameters};
2427 if (!$function->signature->extendedAttributes->{"Custom"} &&
2428 !(GetNativeType($function->signature->type) eq "bool")) {
2429 push(@headerContent, " COMPILE_ASSERT(false)");
2432 push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
2435 foreach my $param (@params) {
2436 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2438 push(@headerContent, join(", ", @args));
2439 push(@headerContent, ");\n");
2443 push(@headerContent, <<END);
2446 ${className}(v8::Local<v8::Object>, ScriptExecutionContext*);
2448 v8::Persistent<v8::Object> m_callback;
2449 WorldContextHandle m_worldContext;
2454 push(@headerContent, "}\n\n");
2455 push(@headerContent, "#endif // $className" . "_h\n\n");
2457 my $conditionalString = GenerateConditionalString($dataNode);
2458 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
2461 sub GenerateCallbackImplementation
2464 my $dataNode = shift;
2465 my $interfaceName = $dataNode->name;
2466 my $className = "V8$interfaceName";
2468 # - Add default header template
2469 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2471 $implIncludes{"ScriptExecutionContext.h"} = 1;
2472 $implIncludes{"V8CustomVoidCallback.h"} = 1;
2473 $implIncludes{"V8Proxy.h"} = 1;
2475 push(@implContent, "#include <wtf/Assertions.h>\n\n");
2476 push(@implContent, "namespace WebCore {\n\n");
2477 push(@implContent, <<END);
2478 ${className}::${className}(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
2479 : ActiveDOMCallback(context)
2480 , m_callback(v8::Persistent<v8::Object>::New(callback))
2481 , m_worldContext(UseCurrentWorld)
2485 ${className}::~${className}()
2487 m_callback.Dispose();
2493 my $numFunctions = @{$dataNode->functions};
2494 if ($numFunctions > 0) {
2495 push(@implContent, "// Functions\n");
2496 foreach my $function (@{$dataNode->functions}) {
2497 my @params = @{$function->parameters};
2498 if ($function->signature->extendedAttributes->{"Custom"} ||
2499 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
2503 AddIncludesForType($function->signature->type);
2504 push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(");
2507 foreach my $param (@params) {
2508 AddIncludesForType($param->type);
2509 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2511 push(@implContent, join(", ", @args));
2513 push(@implContent, ")\n");
2514 push(@implContent, "{\n");
2515 push(@implContent, " if (!canInvokeCallback())\n");
2516 push(@implContent, " return true;\n\n");
2517 push(@implContent, " v8::HandleScope handleScope;\n\n");
2518 push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n");
2519 push(@implContent, " if (v8Context.IsEmpty())\n");
2520 push(@implContent, " return true;\n\n");
2521 push(@implContent, " v8::Context::Scope scope(v8Context);\n\n");
2524 foreach my $param (@params) {
2525 my $paramName = $param->name;
2526 push(@implContent, " v8::Handle<v8::Value> ${paramName}Handle = toV8(${paramName});\n");
2527 push(@implContent, " if (${paramName}Handle.IsEmpty()) {\n");
2528 push(@implContent, " CRASH();\n");
2529 push(@implContent, " return true;\n");
2530 push(@implContent, " }\n");
2531 push(@args, " ${paramName}Handle");
2534 push(@implContent, "\n v8::Handle<v8::Value> argv[] = {\n");
2535 push(@implContent, join(",\n", @args));
2536 push(@implContent, "\n };\n\n");
2537 push(@implContent, " bool callbackReturnValue = false;\n");
2538 push(@implContent, " return !invokeCallback(m_callback, " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
2539 push(@implContent, "}\n");
2543 push(@implContent, "\n} // namespace WebCore\n\n");
2545 my $conditionalString = GenerateConditionalString($dataNode);
2546 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2549 sub GenerateToV8Converters
2551 my $dataNode = shift;
2552 my $interfaceName = shift;
2553 my $className = shift;
2554 my $nativeType = shift;
2555 my $serializedAttribute = shift;
2557 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
2558 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
2559 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
2561 push(@implContent, <<END);
2563 v8::Handle<v8::Object> ${className}::wrapSlow(${nativeType}* impl)
2565 v8::Handle<v8::Object> wrapper;
2569 if (IsNodeSubType($dataNode)) {
2570 push(@implContent, <<END);
2571 if (impl->document()) {
2572 proxy = V8Proxy::retrieve(impl->document()->frame());
2573 if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl)) {
2574 if (proxy->windowShell()->initContextIfNeeded()) {
2575 // initContextIfNeeded may have created a wrapper for the object, retry from the start.
2576 return ${className}::wrap(impl);
2584 if (IsNodeSubType($dataNode)) {
2585 push(@implContent, <<END);
2587 v8::Handle<v8::Context> context;
2589 context = proxy->context();
2591 // Enter the node's context and create the wrapper in that context.
2592 if (!context.IsEmpty())
2597 push(@implContent, <<END);
2598 wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl);
2600 if (IsNodeSubType($dataNode)) {
2601 push(@implContent, <<END);
2602 // Exit the node's context if it was entered.
2603 if (!context.IsEmpty())
2608 push(@implContent, <<END);
2609 if (wrapper.IsEmpty())
2612 push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName);
2614 # Eagerly deserialize attributes of type SerializedScriptValue
2615 # while we're in the right context.
2616 if ($serializedAttribute) {
2617 die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue";
2618 my $attrName = $serializedAttribute->signature->name;
2619 my $attrAttr = "v8::DontDelete";
2620 if ($serializedAttribute->type =~ /^readonly/) {
2621 $attrAttr .= " | v8::ReadOnly";
2623 $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)";
2624 my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
2625 push(@implContent, <<END);
2626 SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}());
2630 if ($domMapFunction) {
2631 push(@implContent, <<END);
2632 ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper));
2636 push(@implContent, <<END);
2642 sub HasCustomToV8Implementation {
2643 # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)?
2645 $interfaceName = shift;
2647 # We generate a custom converter (but JSC doesn't) for the following:
2648 return 1 if $interfaceName eq "CSSStyleSheet";
2649 return 1 if $interfaceName eq "CanvasPixelArray";
2650 return 1 if $interfaceName eq "DOMStringMap";
2651 return 1 if $interfaceName eq "DOMWindow";
2652 return 1 if $interfaceName eq "DOMTokenList";
2653 return 1 if $interfaceName eq "Element";
2654 return 1 if $interfaceName eq "HTMLDocument";
2655 return 1 if $interfaceName eq "HTMLElement";
2656 return 1 if $interfaceName eq "Location";
2657 return 1 if $interfaceName eq "NamedNodeMap";
2658 return 1 if $interfaceName eq "SVGDocument";
2659 return 1 if $interfaceName eq "SVGElement";
2660 return 1 if $interfaceName eq "ScriptProfile";
2661 return 1 if $interfaceName eq "ScriptProfileNode";
2662 return 1 if $interfaceName eq "WorkerContext";
2663 # We don't generate a custom converter (but JSC does) for the following:
2664 return 0 if $interfaceName eq "AbstractWorker";
2665 return 0 if $interfaceName eq "CanvasRenderingContext";
2666 return 0 if $interfaceName eq "ImageData";
2667 return 0 if $interfaceName eq "SVGElementInstance";
2669 # For everything else, do what JSC does.
2670 return $dataNode->extendedAttributes->{"CustomToJS"};
2673 sub GetDomMapFunction
2675 my $dataNode = shift;
2677 return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
2678 return "getDOMNodeMap()" if ($dataNode && IsNodeSubType($dataNode));
2679 # Only use getDOMSVGObjectWithContextMap() for non-node svg objects
2680 return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/ and $type ne "SVGLength" and $type ne "SVGLengthList" and not $codeGenerator->IsSVGNewStyleAnimatedType($type);
2681 return "" if $type eq "DOMImplementation";
2682 return "getActiveDOMObjectMap()" if IsActiveDomType($type);
2683 return "getDOMObjectMap()";
2688 # FIXME: Consider making this an .idl attribute.
2690 return 1 if $type eq "EventSource";
2691 return 1 if $type eq "MessagePort";
2692 return 1 if $type eq "XMLHttpRequest";
2693 return 1 if $type eq "WebSocket";
2694 return 1 if $type eq "Worker";
2695 return 1 if $type eq "SharedWorker";
2696 return 1 if $type eq "IDBRequest";
2697 return 1 if $type eq "FileReader";
2698 return 1 if $type eq "FileWriter";
2702 sub GetNativeTypeForConversions
2704 my $dataNode = shift;
2707 $type = "AffineTransform" if $type eq "SVGMatrix";
2708 $type = "V8SVGPODTypeWrapper<$type>" if $dataNode->extendedAttributes->{"PODType"};
2709 $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->IsSVGTypeNeedingTearOff($type);
2713 sub GenerateFunctionCallString()
2715 my $function = shift;
2716 my $numberOfParameters = shift;
2718 my $implClassName = shift;
2720 my $name = $function->signature->name;
2721 my $isPodType = IsPodType($implClassName);
2722 my $returnType = GetTypeFromSignature($function->signature);
2723 my $returnsPodType = IsPodType($returnType);
2724 my $nativeReturnType = GetNativeType($returnType, 0);
2727 my $isSVGTearOffType = ($codeGenerator->IsSVGTypeNeedingTearOff($returnType) and not $implClassName =~ /List$/);
2728 $nativeReturnType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType;
2730 # Special case: SVG matrix transform methods should not mutate
2731 # the matrix but return a copy
2733 if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
2737 if ($function->signature->extendedAttributes->{"v8implname"}) {
2738 $name = $function->signature->extendedAttributes->{"v8implname"};
2741 if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
2742 $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
2745 my $functionString = "imp->${name}(";
2748 $functionString = "result.${name}(";
2751 if ($function->signature->extendedAttributes->{"ClassMethod"}) {
2752 $functionString = "${implClassName}::${name}(";
2755 my $returnsListItemPodType = 0;
2756 # SVG lists functions that return POD types require special handling
2757 if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
2758 $returnsListItemPodType = 1;
2759 $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
2760 $functionString = "listImp->${name}(";
2764 my $hasScriptState = 0;
2766 my $callWith = $function->signature->extendedAttributes->{"CallWith"};
2768 my $callWithArg = "COMPILE_ASSERT(false)";
2769 if ($callWith eq "DynamicFrame") {
2770 $result .= $indent . "Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext();\n";
2771 $result .= $indent . "if (!enteredFrame)\n";
2772 $result .= $indent . " return v8::Undefined();\n";
2773 $callWithArg = "enteredFrame";
2774 } elsif ($callWith eq "ScriptState") {
2775 $result .= $indent . "EmptyScriptState state;\n";
2776 $callWithArg = "&state";
2777 $hasScriptState = 1;
2778 } elsif ($callWith eq "ScriptExecutionContext") {
2779 $result .= $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n";
2780 $result .= $indent . "if (!scriptContext)\n";
2781 $result .= $indent . " return v8::Undefined();\n";
2782 $callWithArg = "scriptContext";
2784 $functionString .= ", " if $index;
2785 $functionString .= $callWithArg;
2787 $numberOfParameters++
2790 foreach my $parameter (@{$function->parameters}) {
2791 if ($index eq $numberOfParameters) {
2794 $functionString .= ", " if $index;
2795 my $paramName = $parameter->name;
2796 my $paramType = $parameter->type;
2798 # This is a bit of a hack... we need to convert parameters to methods on SVG lists
2799 # of POD types which are items in the list to appropriate SVGList<> instances
2800 if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
2801 $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
2804 if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
2805 $functionString .= "$paramName.get()";
2806 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($parameter->type) and not $implClassName =~ /List$/) {
2807 $functionString .= "$paramName->propertyReference()";
2808 $result .= $indent . "if (!$paramName) {\n";
2809 $result .= $indent . " V8Proxy::setDOMException(WebCore::TYPE_MISMATCH_ERR);\n";
2810 $result .= $indent . " return v8::Handle<v8::Value>();\n";
2811 $result .= $indent . "}\n";
2813 $functionString .= $paramName;
2818 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
2819 $functionString .= ", " if $index;
2820 $functionString .= "scriptArguments.release(), callStack.release()";
2824 if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
2825 $functionString .= ", " if $index;
2826 # FIXME: We need to pass DOMWrapperWorld as a parameter.
2827 # See http://trac.webkit.org/changeset/54182
2828 $functionString .= "processingUserGesture()";
2832 if (@{$function->raisesExceptions}) {
2833 $functionString .= ", " if $index;
2834 $functionString .= "ec";
2837 $functionString .= ")";
2839 my $return = "result";
2840 my $returnIsRef = IsRefPtrType($returnType);
2842 if ($returnType eq "void") {
2843 $result .= $indent . "$functionString;\n";
2844 } elsif ($copyFirst) {
2845 $result .= $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . $indent . "$functionString;\n";
2846 } elsif ($returnsListItemPodType) {
2847 $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
2848 } elsif ($hasScriptState or @{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
2849 $result .= $indent . $nativeReturnType . " result = $functionString;\n";
2851 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
2852 $return = $functionString;
2856 if (@{$function->raisesExceptions}) {
2857 $result .= $indent . "if (UNLIKELY(ec))\n";
2858 $result .= $indent . " goto fail;\n";
2861 if ($hasScriptState) {
2862 $result .= $indent . "if (state.hadException())\n";
2863 $result .= $indent . " return throwError(state.exception());\n"
2866 # If the return type is a POD type, separate out the wrapper generation
2867 if ($returnsListItemPodType) {
2868 $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
2869 $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
2870 $return = "wrapper";
2871 } elsif ($returnsPodType) {
2872 $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
2873 $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
2874 $return = "wrapper";
2877 if ($isSVGTearOffType) {
2878 $implIncludes{"V8$returnType.h"} = 1;
2879 $implIncludes{"SVGPropertyTearOff.h"} = 1;
2880 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($returnType);
2881 $result .= $indent . "return toV8(WTF::getPtr(${svgNativeType}::create($return)));\n";
2885 my $generatedSVGContextRetrieval = 0;
2886 # If the return type needs an SVG context, output it
2887 if (IsSVGTypeNeedingContextParameter($returnType)) {
2888 $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
2889 $generatedSVGContextRetrieval = 1;
2892 if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
2893 if (!$generatedSVGContextRetrieval) {
2894 $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2895 $generatedSVGContextRetrieval = 1;
2898 $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
2899 $implIncludes{"SVGElement.h"} = 1;
2902 # If the implementing class is a POD type, commit changes
2904 if (!$generatedSVGContextRetrieval) {
2905 $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2906 $generatedSVGContextRetrieval = 1;
2909 $result .= $indent . "impWrapper->commitChange(impInstance, context);\n";
2910 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($implClassName) and not $implClassName =~ /List$/) {
2911 $result .= $indent . "wrapper->commitChange();\n";
2914 if ($returnsPodType) {
2915 $implIncludes{"V8${returnType}.h"} = 1;
2916 $result .= $indent . "return toV8(wrapper.release());\n";
2918 $return .= ".release()" if ($returnIsRef);
2919 $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
2926 sub GetTypeFromSignature
2928 my $signature = shift;
2930 return $codeGenerator->StripModule($signature->type);
2934 sub GetNativeTypeFromSignature
2936 my $signature = shift;
2937 my $parameterIndex = shift;
2939 my $type = GetTypeFromSignature($signature);
2941 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
2942 # Special-case index arguments because we need to check that they aren't < 0.
2946 $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
2948 if ($parameterIndex >= 0 && $type eq "V8Parameter") {
2950 if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
2951 $mode = "WithUndefinedOrNullCheck";
2952 } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"}) {
2953 $mode = "WithNullCheck";
2965 return 0 if $type eq "boolean";
2966 return 0 if $type eq "float";
2967 return 0 if $type eq "int";
2968 return 0 if $type eq "Date";
2969 return 0 if $type eq "DOMString";
2970 return 0 if $type eq "double";
2971 return 0 if $type eq "short";
2972 return 0 if $type eq "long";
2973 return 0 if $type eq "unsigned";
2974 return 0 if $type eq "unsigned long";
2975 return 0 if $type eq "unsigned short";
2983 my $isParameter = shift;
2985 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
2986 if ($svgNativeType) {
2987 if ($svgNativeType =~ /List$/) {
2988 return "${svgNativeType}*";
2990 return "RefPtr<${svgNativeType} >";
2994 if ($type eq "float" or $type eq "double") {
2998 return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
2999 return "int" if $type eq "int";
3000 return "int" if $type eq "short" or $type eq "unsigned short";
3001 return "unsigned" if $type eq "unsigned long";
3002 return "int" if $type eq "long";
3003 return "long long" if $type eq "long long";
3004 return "unsigned long long" if $type eq "unsigned long long";
3005 return "bool" if $type eq "boolean";
3006 return "String" if $type eq "DOMString";
3007 return "Range::CompareHow" if $type eq "CompareHow";
3008 return "AffineTransform" if $type eq "SVGMatrix";
3009 return "SVGTransform" if $type eq "SVGTransform";
3010 return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
3011 return "DOMTimeStamp" if $type eq "DOMTimeStamp";
3012 return "unsigned" if $type eq "unsigned int";
3013 return "Node*" if $type eq "EventTarget" and $isParameter;
3014 return "double" if $type eq "Date";
3015 return "ScriptValue" if $type eq "DOMObject";
3017 return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack?
3020 return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
3022 return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
3024 return "RefPtr<IDBKey>" if $type eq "IDBKey";
3026 # necessary as resolvers could be constructed on fly.
3027 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
3029 return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
3031 # Default, assume native type is a pointer with same type name as idl type
3035 sub GetNativeTypeForCallbacks
3038 return "const String&" if $type eq "DOMString";
3040 # Callbacks use raw pointers, so pass isParameter = 1
3041 return GetNativeType($type, 1);
3044 sub TranslateParameter
3046 my $signature = shift;
3048 # The IDL uses some pseudo-types which don't really exist.
3049 if ($signature->type eq "TimeoutHandler") {
3050 $signature->type("DOMString");
3054 sub BasicTypeCanFailConversion
3056 my $signature = shift;
3057 my $type = GetTypeFromSignature($signature);
3059 return 1 if $type eq "SVGMatrix";
3060 return 1 if $type eq "SVGTransform";
3064 sub TypeCanFailConversion
3066 my $signature = shift;
3068 my $type = GetTypeFromSignature($signature);
3070 $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
3071 return 1 if $type eq "Attr";
3072 return 1 if $type eq "VoidCallback";
3073 return 1 if $type eq "IDBKey";
3074 return BasicTypeCanFailConversion($signature);
3079 my $signature = shift;
3081 my $okParam = shift;
3082 my $maybeOkParam = $okParam ? ", ${okParam}" : "";
3084 my $type = GetTypeFromSignature($signature);
3086 return "$value" if $type eq "JSObject";
3087 return "$value->BooleanValue()" if $type eq "boolean";
3088 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
3090 return "toInt32($value${maybeOkParam})" if $type eq "long";
3091 return "toUInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short";
3092 return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
3093 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
3094 return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
3095 return "toWebCoreDate($value)" if $type eq "Date";
3097 if ($type eq "DOMString" or $type eq "DOMUserData") {
3101 die "Unexpected SerializedScriptValue" if $type eq "SerializedScriptValue";
3103 if ($type eq "IDBKey") {
3104 $implIncludes{"IDBBindingUtilities.h"} = 1;
3105 $implIncludes{"IDBKey.h"} = 1;
3106 return "createIDBKeyFromValue($value)";
3109 if ($type eq "DOMObject") {
3110 $implIncludes{"ScriptValue.h"} = 1;
3111 return "ScriptValue($value)";
3114 if ($type eq "NodeFilter") {
3115 return "V8DOMWrapper::wrapNativeNodeFilter($value)";
3118 if ($type eq "SVGRect") {
3119 $implIncludes{"FloatRect.h"} = 1;
3122 # Default, assume autogenerated type conversion routines
3123 if ($type eq "EventTarget") {
3124 $implIncludes{"V8Node.h"} = 1;
3126 # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
3127 return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3130 if ($type eq "XPathNSResolver") {
3131 return "V8DOMWrapper::getXPathNSResolver($value)";
3134 AddIncludesForType($type);
3136 if (IsDOMNodeType($type)) {
3137 $implIncludes{"V8${type}.h"} = 1;
3139 # Perform type checks on the parameter, if it is expected Node type,
3141 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3143 $implIncludes{"V8$type.h"} = 1;
3145 if (IsPodType($type)) {
3146 my $nativeType = GetNativeType($type);
3147 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
3149 return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(&V8${type}::info, $value${maybeOkParam})"
3152 $implIncludes{"V8${type}.h"} = 1;
3154 # Perform type checks on the parameter, if it is expected Node type,
3156 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3163 return "V8Event.h" if $type eq "DOMTimeStamp";
3164 return "EventListener.h" if $type eq "EventListener";
3165 return "EventTarget.h" if $type eq "EventTarget";
3166 return "SerializedScriptValue.h" if $type eq "SerializedScriptValue";
3167 return "ScriptValue.h" if $type eq "DOMObject";
3168 return "V8${type}.h";
3171 sub CreateCustomSignature
3173 my $function = shift;
3174 my $count = @{$function->parameters};
3175 my $name = $function->signature->name;
3176 my $result = " const int ${name}Argc = ${count};\n" .
3177 " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { ";
3179 foreach my $parameter (@{$function->parameters}) {
3180 if ($first) { $first = 0; }
3181 else { $result .= ", "; }
3182 if (IsWrapperType($parameter->type)) {
3183 if ($parameter->type eq "XPathNSResolver") {
3184 # Special case for XPathNSResolver. All other browsers accepts a callable,
3185 # so, even though it's against IDL, accept objects here.
3186 $result .= "v8::Handle<v8::FunctionTemplate>()";
3188 my $type = $parameter->type;
3189 my $header = GetV8HeaderName($type);
3190 $implIncludes{$header} = 1;
3191 $result .= "V8${type}::GetRawTemplate()";
3194 $result .= "v8::Handle<v8::FunctionTemplate>()";
3198 $result .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n";
3203 sub RequiresCustomSignature
3205 my $function = shift;
3206 # No signature needed for Custom function
3207 if ($function->signature->extendedAttributes->{"Custom"} ||
3208 $function->signature->extendedAttributes->{"V8Custom"}) {
3211 # No signature needed for overloaded function
3212 if (@{$function->{overloads}} > 1) {
3215 # Type checking is performed in the generated code
3216 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
3219 foreach my $parameter (@{$function->parameters}) {
3220 if ($parameter->extendedAttributes->{"Optional"} || $parameter->extendedAttributes->{"Callback"}) {
3225 foreach my $parameter (@{$function->parameters}) {
3226 if (IsWrapperType($parameter->type)) {
3234 # FIXME: Sort this array.
3235 my %non_wrapper_types = (
3239 'unsigned int' => 1,
3241 'unsigned short' => 1,
3243 'unsigned long' => 1,
3246 'unsigned long long' => 1,
3249 'SerializedScriptValue' => 1,
3253 'SVGPreserveAspectRatio' => 1,
3255 'SVGTransform' => 1,
3258 'SVGPaintType' => 1,
3259 'DOMTimeStamp' => 1,
3264 'EventListener' => 1,
3272 my $type = $codeGenerator->StripModule(shift);
3273 return !($non_wrapper_types{$type});
3280 return 1 if $type eq 'Attr';
3281 return 1 if $type eq 'CDATASection';
3282 return 1 if $type eq 'Comment';
3283 return 1 if $type eq 'Document';
3284 return 1 if $type eq 'DocumentFragment';
3285 return 1 if $type eq 'DocumentType';
3286 return 1 if $type eq 'Element';
3287 return 1 if $type eq 'EntityReference';
3288 return 1 if $type eq 'HTMLCanvasElement';
3289 return 1 if $type eq 'HTMLDocument';
3290 return 1 if $type eq 'HTMLElement';
3291 return 1 if $type eq 'HTMLFormElement';
3292 return 1 if $type eq 'HTMLTableCaptionElement';
3293 return 1 if $type eq 'HTMLTableSectionElement';
3294 return 1 if $type eq 'Node';
3295 return 1 if $type eq 'ProcessingInstruction';
3296 return 1 if $type eq 'SVGElement';
3297 return 1 if $type eq 'SVGDocument';
3298 return 1 if $type eq 'SVGSVGElement';
3299 return 1 if $type eq 'SVGUseElement';
3300 return 1 if $type eq 'Text';
3306 sub ReturnNativeToJSValue
3308 my $signature = shift;
3311 my $type = GetTypeFromSignature($signature);
3313 return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
3314 return "return v8Boolean($value)" if $type eq "boolean";
3315 return "return v8::Handle<v8::Value>()" if $type eq "void"; # equivalent to v8::Undefined()
3317 # For all the types where we use 'int' as the representation type,
3318 # we use Integer::New which has a fast Smi conversion check.
3319 my $nativeType = GetNativeType($type);
3320 return "return v8::Integer::New($value)" if $nativeType eq "int";
3321 return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
3323 return "return v8DateOrNull($value)" if $type eq "Date";
3324 # long long and unsigned long long are not representable in ECMAScript.
3325 return "return v8::Number::New(static_cast<double>($value))" if $type eq "long long" or $type eq "unsigned long long";
3326 return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
3327 return "return $value.v8Value()" if $nativeType eq "ScriptValue";
3329 if ($codeGenerator->IsStringType($type)) {
3330 my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
3331 if (defined $conv) {
3332 return "return v8StringOrNull($value)" if $conv eq "Null";
3333 return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
3334 return "return v8StringOrFalse($value)" if $conv eq "False";
3336 die "Unknown value for ConvertNullStringTo extended attribute";
3338 $conv = $signature->extendedAttributes->{"ConvertScriptString"};
3339 return "return v8StringOrNull($value)" if $conv;
3340 return "return v8String($value)";
3343 AddIncludesForType($type);
3345 # special case for non-DOM node interfaces
3346 if (IsDOMNodeType($type)) {
3347 return "return toV8(${value}" . ($signature->extendedAttributes->{"ReturnsNew"} ? ", true)" : ")");
3350 if ($type eq "EventTarget") {
3351 return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
3354 if ($type eq "EventListener") {
3355 $implIncludes{"V8AbstractEventListener.h"} = 1;
3356 return "return ${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null())";
3359 if ($type eq "SerializedScriptValue") {
3360 $implIncludes{"$type.h"} = 1;
3361 return "return $value->deserialize()";
3364 $implIncludes{"wtf/RefCounted.h"} = 1;
3365 $implIncludes{"wtf/RefPtr.h"} = 1;
3366 $implIncludes{"wtf/GetPtr.h"} = 1;
3368 if (IsPodType($type)) {
3369 $value = GenerateSVGStaticPodTypeWrapper($type, $value) . ".get()";
3372 return "return toV8($value)";
3375 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
3376 sub GenerateSVGStaticPodTypeWrapper {
3380 $implIncludes{"V8$type.h"}=1;
3381 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
3383 my $nativeType = GetNativeType($type);
3384 return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
3390 if (defined($IMPL)) {
3391 # Write content to file.
3392 print $IMPL @implContentHeader;
3394 print $IMPL @implFixedHeader;
3396 foreach my $implInclude (sort keys(%implIncludes)) {
3397 my $checkType = $implInclude;
3398 $checkType =~ s/\.h//;
3400 if ($implInclude =~ /wtf/) {
3401 print $IMPL "#include \<$implInclude\>\n";
3403 print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
3408 print $IMPL @implContentDecls;
3409 print $IMPL @implContent;
3414 @implFixedHeader = ();
3415 @implHeaderContent = ();
3416 @implContentDecls = ();
3420 if (defined($HEADER)) {
3421 # Write content to file.
3422 print $HEADER @headerContent;
3426 @headerContent = ();
3430 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
3431 sub IsSVGTypeNeedingContextParameter
3433 my $implClassName = shift;
3435 return 0 unless $implClassName =~ /SVG/;
3436 return 0 if $implClassName =~ /Element/;
3437 return 0 if $codeGenerator->IsSVGNewStyleAnimatedType($implClassName);
3438 return 0 if $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
3440 my @noContextNeeded = ("SVGColor", "SVGDocument", "SVGPaintType", "SVGPaint", "SVGZoomEvent");
3441 foreach (@noContextNeeded) {
3442 return 0 if $implClassName eq $_;
3447 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
3448 sub GenerateSVGContextAssignment
3450 my $srcType = shift;
3454 $result = GenerateSVGContextRetrieval($srcType, $indent);
3455 $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
3460 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
3461 sub GenerateSVGContextRetrieval
3463 my $srcType = shift;
3466 my $srcIsPodType = IsPodType($srcType);
3468 my $srcObject = "imp";
3469 if ($srcIsPodType) {
3470 $srcObject = "impWrapper";
3475 if (IsSVGTypeNeedingContextParameter($srcType)) {
3476 $contextDecl = "V8Proxy::svgContext($srcObject)";
3478 $contextDecl = $srcObject;
3481 return $indent . "SVGElement* context = $contextDecl;\n";
3484 sub IsSVGListMutator
3486 my $functionName = shift;
3488 return 1 if $functionName eq "clear";
3489 return 1 if $functionName eq "initialize";
3490 return 1 if $functionName eq "insertItemBefore";
3491 return 1 if $functionName eq "replaceItem";
3492 return 1 if $functionName eq "removeItem";
3493 return 1 if $functionName eq "appendItem";
3500 my $functionName = shift;
3502 return 1 if $functionName eq "getFirst";
3503 return 1 if $functionName eq "getLast";
3504 return 1 if $functionName eq "getItem";
3506 return IsSVGListMutator($functionName);
3509 sub IsSVGListTypeNeedingSpecialHandling
3511 my $className = shift;
3513 return 1 if $className eq "SVGTransformList";
3518 sub GetVisibleInterfaceName
3520 my $interfaceName = shift;
3522 return "DOMException" if $interfaceName eq "DOMCoreException";
3523 return "FormData" if $interfaceName eq "DOMFormData";
3524 return $interfaceName;
3527 sub GetCallbackClassName
3529 my $interfaceName = shift;
3531 return "V8CustomVoidCallback" if $interfaceName eq "VoidCallback";
3532 return "V8$interfaceName";
3535 sub ConvertToV8Parameter
3537 my $signature = shift;
3538 my $nativeType = shift;
3539 my $variableName = shift;
3543 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8Parameter/;
3544 if ($signature->type eq "DOMString") {
3545 $implIncludes{"V8BindingMacros.h"} = 1;
3546 my $macro = "STRING_TO_V8PARAMETER_EXCEPTION_BLOCK";
3547 $macro .= "_$suffix" if $suffix;
3548 return "$macro($nativeType, $variableName, $value);"
3550 # Don't know how to properly check for conversion exceptions when $parameter->type is "DOMUserData"
3551 return "$nativeType $variableName($value, true);";
3555 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
3556 sub GetRuntimeEnableFunctionName
3558 my $signature = shift;
3560 # If a parameter is given (e.g. "EnabledAtRuntime=FeatureName") return the RuntimeEnabledFeatures::{FeatureName}Enabled() method.
3561 return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->extendedAttributes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"EnabledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "1");
3563 # Otherwise return a function named RuntimeEnabledFeatures::{methodName}Enabled().
3564 return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->name) . "Enabled";