1 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
2 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
3 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
4 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
5 # Copyright (C) 2006 Apple Computer, Inc.
6 # Copyright (C) 2007, 2008, 2009 Google Inc.
7 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
8 # Copyright (C) Research In Motion Limited 2010. All rights reserved.
10 # This library is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU Library General Public
12 # License as published by the Free Software Foundation; either
13 # version 2 of the License, or (at your option) any later version.
15 # This library is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 # Library General Public License for more details.
20 # You should have received a copy of the GNU Library General Public License
21 # along with this library; see the file COPYING.LIB. If not, write to
22 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 # Boston, MA 02111-1307, USA.
26 package CodeGeneratorV8;
33 my $outputHeadersDir = "";
35 my @headerContent = ();
36 my @implContentHeader = ();
37 my @implFixedHeader = ();
39 my @implContentDecls = ();
40 my %implIncludes = ();
41 my %headerIncludes = ();
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 # Params: 'domClass' struct
97 # Start actual generation
98 if ($dataNode->extendedAttributes->{"Callback"}) {
99 $object->GenerateCallbackHeader($dataNode);
100 $object->GenerateCallbackImplementation($dataNode);
102 $object->GenerateHeader($dataNode);
103 $object->GenerateImplementation($dataNode);
106 my $name = $dataNode->name;
108 # Open files for writing
109 my $headerFileName = "$outputHeadersDir/V8$name.h";
110 my $implFileName = "$outputDir/V8$name.cpp";
112 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
113 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
116 # Params: 'idlDocument' struct
120 my $dataNode = shift;
122 $module = $dataNode->module;
125 sub AddIncludesForType
127 my $type = $codeGenerator->StripModule(shift);
129 # When we're finished with the one-file-per-class
130 # reorganization, we won't need these special cases.
131 if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->AvoidInclusionOfType($type) and $type ne "Date") {
132 # default, include the same named file
133 $implIncludes{GetV8HeaderName(${type})} = 1;
135 if ($type =~ /SVGPathSeg/) {
137 $joinedName =~ s/Abs|Rel//;
138 $implIncludes{"${joinedName}.h"} = 1;
142 # additional includes (things needed to compile the bindings but not the header)
144 if ($type eq "CanvasRenderingContext2D") {
145 $implIncludes{"CanvasGradient.h"} = 1;
146 $implIncludes{"CanvasPattern.h"} = 1;
147 $implIncludes{"CanvasStyle.h"} = 1;
150 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
151 $implIncludes{"PlatformString.h"} = 1;
154 if ($type eq "CSSStyleDeclaration") {
155 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
158 if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
159 # So we can get String -> AtomicString conversion for namedItem().
160 $implIncludes{"wtf/text/AtomicString.h"} = 1;
164 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
165 sub GenerateConditionalString
168 my $conditional = $node->extendedAttributes->{"Conditional"};
170 if ($conditional =~ /&/) {
171 return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
172 } elsif ($conditional =~ /\|/) {
173 return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
175 return "ENABLE(" . $conditional . ")";
182 sub GetSVGPropertyTypes
184 my $implType = shift;
187 my $svgListPropertyType;
190 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
192 $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
193 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
195 # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType>
196 $svgNativeType = "$svgNativeType ";
198 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
199 if ($svgNativeType =~ /SVGPropertyTearOff/) {
200 $svgPropertyType = $svgWrappedNativeType;
201 $implIncludes{"SVGAnimatedPropertyTearOff.h"} = 1;
202 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
203 $svgListPropertyType = $svgWrappedNativeType;
204 $implIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
205 } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
206 $svgListPropertyType = $svgWrappedNativeType;
207 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
208 $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
209 } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
210 $svgListPropertyType = $svgWrappedNativeType;
211 $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
214 if ($svgPropertyType) {
215 $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint";
218 return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
224 my $dataNode = shift;
226 my $interfaceName = $dataNode->name;
227 my $className = "V8$interfaceName";
228 my $implClassName = $interfaceName;
230 # Copy contents of parent classes except the first parent or if it is
232 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
234 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
236 # - Add default header template
237 push(@headerContent, GenerateHeaderContentHeader($dataNode));
239 $headerIncludes{"wtf/text/StringHash.h"} = 1;
240 $headerIncludes{"WrapperTypeInfo.h"} = 1;
241 $headerIncludes{"V8DOMWrapper.h"} = 1;
243 my $headerClassInclude = GetHeaderClassInclude($implClassName);
244 $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
246 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
248 foreach my $headerInclude (sort keys(%headerIncludes)) {
249 push(@headerContent, "#include \"${headerInclude}\"\n");
252 push(@headerContent, "#include <v8.h>\n");
253 push(@headerContent, "#include <wtf/HashMap.h>\n");
255 push(@headerContent, "\nnamespace WebCore {\n");
256 push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
257 if ($svgNativeType) {
258 if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
259 push(@headerContent, "\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
261 push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
264 push(@headerContent, "\nclass FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect";
265 push(@headerContent, "\nclass $className {\n");
267 my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
268 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
269 my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
270 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
271 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
273 push(@headerContent, <<END);
276 static bool HasInstance(v8::Handle<v8::Value> value);
277 static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
278 static v8::Persistent<v8::FunctionTemplate> GetTemplate();
279 static ${nativeType}* toNative(v8::Handle<v8::Object> object)
281 return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
283 inline static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
284 static void derefObject(void*);
285 static WrapperTypeInfo info;
287 if (IsActiveDomType($implClassName)) {
288 push(@headerContent, " static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
291 if ($implClassName eq "DOMWindow") {
292 push(@headerContent, <<END);
293 static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
297 if ($implClassName eq "HTMLDocument") {
298 push(@headerContent, <<END);
299 static v8::Local<v8::Object> WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl);
300 static v8::Handle<v8::Value> GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key);
304 my @enabledAtRuntime;
305 foreach my $function (@{$dataNode->functions}) {
306 my $name = $function->signature->name;
307 my $attrExt = $function->signature->extendedAttributes;
309 if ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
310 push(@headerContent, <<END);
311 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
315 if ($attrExt->{"EnabledAtRuntime"}) {
316 push(@enabledAtRuntime, $function);
320 if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
321 push(@headerContent, <<END);
322 static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args);
326 foreach my $attribute (@{$dataNode->attributes}) {
327 my $name = $attribute->signature->name;
328 my $attrExt = $attribute->signature->extendedAttributes;
329 if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"}
330 || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
331 push(@headerContent, <<END);
332 static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
335 if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"}
336 || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
337 push(@headerContent, <<END);
338 static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
341 if ($attrExt->{"EnabledAtRuntime"}) {
342 push(@enabledAtRuntime, $attribute);
346 GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
347 GenerateHeaderCustomCall($dataNode);
348 GenerateHeaderCustomInternalFieldIndices($dataNode);
350 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
351 push(@headerContent, <<END);
352 static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
353 static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
357 push(@headerContent, <<END);
359 static v8::Handle<v8::Object> wrapSlow(${nativeType}*);
364 push(@headerContent, <<END);
366 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput})
369 if ($domMapFunction) {
370 push(@headerContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
371 my $getWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getWrapper(impl)" : "${domMapFunction}.get(impl)";
372 push(@headerContent, <<END);
373 v8::Handle<v8::Object> wrapper = ${getWrapper};
374 if (!wrapper.IsEmpty())
377 push(@headerContent, " }\n") if IsDOMNodeType($interfaceName);
379 push(@headerContent, <<END);
380 return ${className}::wrapSlow(impl);
384 if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
385 push(@headerContent, <<END);
387 inline v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectParameter})
391 return ${className}::wrap(impl${forceNewObjectCall});
394 } elsif ($interfaceName ne 'Node') {
395 push(@headerContent, <<END);
397 v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
400 push(@headerContent, <<END);
402 v8::Handle<v8::Value> toV8Slow(Node*, bool);
404 inline v8::Handle<v8::Value> toV8(Node* impl, bool forceNewObject = false)
408 if (!forceNewObject) {
409 v8::Handle<v8::Value> wrapper = V8DOMWrapper::getWrapper(impl);
410 if (!wrapper.IsEmpty())
413 return toV8Slow(impl, forceNewObject);
418 if (IsRefPtrType($implClassName)) {
419 push(@headerContent, <<END);
420 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl${forceNewObjectParameter})
422 return toV8(impl.get()${forceNewObjectCall});
427 push(@headerContent, "}\n\n");
428 push(@headerContent, "#endif // $className" . "_h\n");
430 my $conditionalString = GenerateConditionalString($dataNode);
431 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
434 sub GetInternalFields
436 my $dataNode = shift;
437 my $name = $dataNode->name;
439 my @customInternalFields = ();
441 # We can't ask whether a parent type has a given extendedAttribute, so special-case Node, AbstractWorker and WorkerContext to include all sub-types.
442 # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't.
443 if ($dataNode->extendedAttributes->{"EventTarget"} || IsNodeSubType($dataNode) || IsSubType($dataNode, "AbstractWorker") || IsSubType($dataNode, "WorkerContext")
444 || $name eq "SVGElementInstance") {
445 push(@customInternalFields, "eventListenerCacheIndex");
448 if (IsSubType($dataNode, "Document")) {
449 push(@customInternalFields, "implementationIndex");
450 } elsif ($name eq "DOMWindow") {
451 push(@customInternalFields, "enteredIsolatedWorldIndex");
453 return @customInternalFields;
456 sub GetHeaderClassInclude
458 my $className = shift;
459 if ($className =~ /SVGPathSeg/) {
460 $className =~ s/Abs|Rel//;
462 return "" if ($codeGenerator->AvoidInclusionOfType($className));
463 return "${className}.h";
466 sub GenerateHeaderCustomInternalFieldIndices
468 my $dataNode = shift;
469 my @customInternalFields = GetInternalFields($dataNode);
470 my $customFieldCounter = 0;
471 foreach my $customInternalField (@customInternalFields) {
472 push(@headerContent, <<END);
473 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
475 $customFieldCounter++;
477 push(@headerContent, <<END);
478 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
482 my %indexerSpecialCases = (
484 "HTMLAppletElement" => 1,
485 "HTMLEmbedElement" => 1,
486 "HTMLObjectElement" => 1
489 sub GenerateHeaderNamedAndIndexedPropertyAccessors
491 my $dataNode = shift;
492 my $interfaceName = $dataNode->name;
493 my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
494 my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
495 my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
496 my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
497 my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
498 my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
499 if ($interfaceName eq "HTMLOptionsCollection") {
500 $interfaceName = "HTMLCollection";
501 $hasCustomIndexedGetter = 1;
502 $hasCustomNamedGetter = 1;
504 if ($interfaceName eq "DOMWindow") {
505 $hasCustomDeleterr = 0;
508 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
509 $hasCustomNamedGetter = 1;
511 if ($interfaceName eq "HTMLDocument") {
512 $hasCustomNamedGetter = 0;
513 $hasCustomIndexedGetter = 0;
515 my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
517 if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
518 push(@headerContent, <<END);
519 static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
523 if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
524 push(@headerContent, <<END);
525 static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
528 if ($hasCustomDeleters) {
529 push(@headerContent, <<END);
530 static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
533 if ($hasCustomNamedGetter) {
534 push(@headerContent, <<END);
535 static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
538 if ($hasCustomNamedSetter) {
539 push(@headerContent, <<END);
540 static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
543 if ($hasCustomDeleters) {
544 push(@headerContent, <<END);
545 static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
548 if ($hasCustomEnumerator) {
549 push(@headerContent, <<END);
550 static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
551 static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
556 sub GenerateHeaderCustomCall
558 my $dataNode = shift;
560 if ($dataNode->extendedAttributes->{"CustomCall"}) {
561 push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
563 if ($dataNode->name eq "Event") {
564 push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
565 push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n");
567 if ($dataNode->name eq "Location") {
568 push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
569 push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
570 push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
574 sub GenerateSetDOMException
579 $result .= $indent . "if (UNLIKELY(ec)) {\n";
580 $result .= $indent . " V8Proxy::setDOMException(ec);\n";
581 $result .= $indent . " return v8::Handle<v8::Value>();\n";
582 $result .= $indent . "}\n";
589 my $dataNode = shift;
590 my $parentType = shift;
591 return 1 if ($dataNode->name eq $parentType);
592 foreach (@allParents) {
593 my $parent = $codeGenerator->StripModule($_);
594 return 1 if $parent eq $parentType;
601 my $dataNode = shift;
602 return IsSubType($dataNode, "Node");
605 sub GenerateDomainSafeFunctionGetter
607 my $function = shift;
608 my $implClassName = shift;
610 my $className = "V8" . $implClassName;
611 my $funcName = $function->signature->name;
613 my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
614 if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
615 $signature = "v8::Local<v8::Signature>()";
618 my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature);
620 push(@implContentDecls, <<END);
621 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
623 INC_STATS(\"DOM.$implClassName.$funcName._get\");
624 static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
625 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
626 if (holder.IsEmpty()) {
627 // can only reach here by 'object.__proto__.func', and it should passed
628 // domain security check already
629 return privateTemplate->GetFunction();
631 ${implClassName}* imp = ${className}::toNative(holder);
632 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
633 static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
634 return sharedTemplate->GetFunction();
636 return privateTemplate->GetFunction();
642 sub GenerateConstructorGetter
644 my $implClassName = shift;
646 push(@implContentDecls, <<END);
647 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
649 INC_STATS(\"DOM.$implClassName.constructors._get\");
650 v8::Handle<v8::Value> data = info.Data();
651 ASSERT(data->IsExternal() || data->IsNumber());
652 WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data);
655 if ($implClassName eq "DOMWindow") {
656 push(@implContentDecls, <<END);
657 // Get the proxy corresponding to the DOMWindow if possible to
658 // make sure that the constructor function is constructed in the
659 // context of the DOMWindow and not in the context of the caller.
660 return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder()));
662 } elsif ($implClassName eq "DedicatedWorkerContext" or $implClassName eq "WorkerContext" or $implClassName eq "SharedWorkerContext") {
663 push(@implContentDecls, <<END);
664 return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder()));
667 push(@implContentDecls, " return v8::Handle<v8::Value>();");
670 push(@implContentDecls, <<END);
676 sub GenerateNormalAttrGetter
678 my $attribute = shift;
679 my $dataNode = shift;
680 my $implClassName = shift;
681 my $interfaceName = shift;
683 my $attrExt = $attribute->signature->extendedAttributes;
685 my $attrName = $attribute->signature->name;
687 my $attrType = GetTypeFromSignature($attribute->signature);
689 my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
692 # Special case: SVGZoomEvent's attributes are all read-only
693 if ($implClassName eq "SVGZoomEvent") {
697 my $getterStringUsesImp = $implClassName ne "SVGNumber";
698 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
701 my $conditionalString = GenerateConditionalString($attribute->signature);
702 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
704 push(@implContentDecls, <<END);
705 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
707 INC_STATS(\"DOM.$implClassName.$attrName._get\");
710 if ($svgNativeType) {
711 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
712 if ($svgWrappedNativeType =~ /List/) {
713 push(@implContentDecls, <<END);
714 $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
717 push(@implContentDecls, <<END);
718 $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());
719 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
721 if ($getterStringUsesImp) {
722 push(@implContentDecls, <<END);
723 $svgWrappedNativeType* imp = &impInstance;
727 } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
728 if ($interfaceName eq "DOMWindow") {
729 push(@implContentDecls, <<END);
730 v8::Handle<v8::Object> holder = info.Holder();
733 # perform lookup first
734 push(@implContentDecls, <<END);
735 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
736 if (holder.IsEmpty())
737 return v8::Handle<v8::Value>();
740 push(@implContentDecls, <<END);
741 ${implClassName}* imp = V8${implClassName}::toNative(holder);
744 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
745 my $url = $attribute->signature->extendedAttributes->{"URL"};
746 if ($getterStringUsesImp && $reflect && !$url && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
747 # Generate super-compact call for regular attribute getter:
748 my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect;
749 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
750 $implIncludes{"${namespace}.h"} = 1;
751 push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
752 push(@implContentDecls, "}\n\n");
753 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
755 # Skip the rest of the function!
757 push(@implContentDecls, <<END);
758 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
762 # Generate security checks if necessary
763 if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
764 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName()))\n return v8::Handle<v8::Value>();\n\n");
765 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
766 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument()))\n return v8::Handle<v8::Value>();\n\n");
769 my $useExceptions = 1 if @{$attribute->getterExceptions};
770 if ($useExceptions) {
771 $implIncludes{"ExceptionCode.h"} = 1;
772 push(@implContentDecls, " ExceptionCode ec = 0;\n");
775 if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
776 $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
779 my $returnType = GetTypeFromSignature($attribute->signature);
782 if ($getterStringUsesImp) {
783 $getterString = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
784 $getterString .= "ec" if $useExceptions;
785 $getterString .= ")";
787 $getterString = "impInstance";
793 if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
794 push(@implContentDecls, " if (!imp->document())\n");
795 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
798 if ($useExceptions) {
799 if ($nativeType =~ /^V8Parameter/) {
800 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $getterString) . ";\n");
802 push(@implContentDecls, " $nativeType v = $getterString;\n");
804 push(@implContentDecls, GenerateSetDOMException(" "));
806 $result .= ".release()" if (IsRefPtrType($returnType));
808 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
809 $result = $getterString;
812 # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
813 # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
814 # the newly created wrapper into an internal field of the holder object.
815 if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"})
816 && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow"
817 && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) {
818 AddIncludesForType($returnType);
819 my $domMapFunction = GetDomMapFunction(0, $returnType);
820 # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
821 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
822 push(@implContentDecls, " RefPtr<$returnType> result = ${getterString};\n");
823 push(@implContentDecls, " v8::Handle<v8::Value> wrapper = result.get() ? ${domMapFunction}.get(result.get()) : v8::Handle<v8::Value>();\n");
824 push(@implContentDecls, " if (wrapper.IsEmpty()) {\n");
825 push(@implContentDecls, " wrapper = toV8(result.get());\n");
826 push(@implContentDecls, " if (!wrapper.IsEmpty())\n");
827 if ($dataNode->name eq "DOMWindow") {
828 push(@implContentDecls, " V8DOMWrapper::setHiddenWindowReference(imp->frame(), wrapper);\n");
830 push(@implContentDecls, " V8DOMWrapper::setHiddenReference(info.Holder(), wrapper);\n");
832 push(@implContentDecls, " }\n");
833 push(@implContentDecls, " return wrapper;\n");
834 push(@implContentDecls, "}\n\n");
835 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
839 if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
840 push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, " "));
841 # The templating associated with passing withSVGContext()'s return value directly into toV8 can get compilers confused,
842 # so just manually set the return value to a PassRefPtr of the expected type.
843 push(@implContentDecls, " PassRefPtr<$attrType> resultAsPassRefPtr = V8Proxy::withSVGContext($result, context);\n");
844 $result = "resultAsPassRefPtr";
847 if ($codeGenerator->IsSVGAnimatedType($implClassName) and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) {
848 $implIncludes{"V8$attrType.h"} = 1;
849 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
850 # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
851 push(@implContentDecls, " return toV8(static_cast<$svgNativeType*>($result));\n");
852 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $implClassName =~ /List$/) {
853 $implIncludes{"V8$attrType.h"} = 1;
854 $implIncludes{"SVGPropertyTearOff.h"} = 1;
855 my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
856 if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
857 my $getter = $result;
858 $getter =~ s/imp->//;
861 my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter);
863 my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
864 if ($selfIsTearOffType) {
865 $implIncludes{"SVGStaticPropertyWithParentTearOff.h"} = 1;
866 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /;
868 if ($result =~ /matrix/ and $implClassName eq "SVGTransform") {
869 # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
870 # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
871 $result =~ s/matrix/svgMatrix/;
874 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(wrapper, $result, $updateMethod)));\n");
876 $implIncludes{"SVGStaticPropertyTearOff.h"} = 1;
877 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
879 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(imp, $result, $updateMethod)));\n");
881 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
882 my $extraImp = "GetOwnerElementForType<$implClassName, IsDerivedFromSVGElement<$implClassName>::value>::ownerElement(imp), ";
883 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create($extraImp$result)));\n");
884 } elsif ($tearOffType =~ /SVGPointList/) {
885 push(@implContentDecls, " return toV8(WTF::getPtr($result));\n");
887 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create($result)));\n");
890 push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n");
893 push(@implContentDecls, "}\n\n"); # end of getter
894 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
897 sub GenerateNormalAttrSetter
899 my $attribute = shift;
900 my $dataNode = shift;
901 my $implClassName = shift;
902 my $interfaceName = shift;
904 $implIncludes{"V8BindingMacros.h"} = 1;
906 my $attrExt = $attribute->signature->extendedAttributes;
908 my $conditionalString = GenerateConditionalString($attribute->signature);
909 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
911 push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
912 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
914 # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
915 # interface type, then if the incoming value does not implement that interface, a TypeError is
916 # thrown rather than silently passing NULL to the C++ code.
917 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
918 # strings and numbers, so do not throw TypeError if the attribute is of these types.
919 if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
920 my $argType = GetTypeFromSignature($attribute->signature);
921 if (IsWrapperType($argType)) {
922 push(@implContentDecls, " if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value)) {\n");
923 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
924 push(@implContentDecls, " return;\n");
925 push(@implContentDecls, " }\n");
929 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
930 if ($svgNativeType) {
931 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
932 if ($svgWrappedNativeType =~ /List$/) {
933 push(@implContentDecls, <<END);
934 $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
937 push(@implContentDecls, <<END);
938 $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());
939 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
940 $svgWrappedNativeType* imp = &impInstance;
943 } elsif ($attrExt->{"v8OnProto"}) {
944 if ($interfaceName eq "DOMWindow") {
945 push(@implContentDecls, <<END);
946 v8::Handle<v8::Object> holder = info.Holder();
949 # perform lookup first
950 push(@implContentDecls, <<END);
951 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
952 if (holder.IsEmpty())
956 push(@implContentDecls, <<END);
957 ${implClassName}* imp = V8${implClassName}::toNative(holder);
960 my $attrType = GetTypeFromSignature($attribute->signature);
961 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
962 if ($reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
963 # Generate super-compact call for regular attribute setter:
964 my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect;
965 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
966 $implIncludes{"${namespace}.h"} = 1;
967 push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
968 push(@implContentDecls, "}\n\n");
969 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
971 # Skip the rest of the function!
974 push(@implContentDecls, <<END);
975 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
979 my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
980 if ($attribute->signature->type eq "EventListener") {
981 if ($dataNode->name eq "DOMWindow") {
982 push(@implContentDecls, " if (!imp->document())\n");
983 push(@implContentDecls, " return;\n");
986 my $value = JSValueToNative($attribute->signature, "value");
987 if ($nativeType =~ /^V8Parameter/) {
988 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
990 push(@implContentDecls, " $nativeType v = $value;\n");
995 my $returnType = GetTypeFromSignature($attribute->signature);
996 if (IsRefPtrType($returnType)) {
997 $result = "WTF::getPtr(" . $result . ")";
1000 my $useExceptions = 1 if @{$attribute->setterExceptions};
1002 if ($useExceptions) {
1003 $implIncludes{"ExceptionCode.h"} = 1;
1004 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1007 if ($implClassName eq "SVGNumber") {
1008 push(@implContentDecls, " *imp = $result;\n");
1010 if ($attribute->signature->type eq "EventListener") {
1011 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
1012 $implIncludes{"V8AbstractEventListener.h"} = 1;
1013 push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n");
1014 if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
1015 $implIncludes{"V8EventListenerList.h"} = 1;
1016 $implIncludes{"V8WorkerContextErrorHandler.h"} = 1;
1017 push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
1019 push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)");
1022 my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
1023 push(@implContentDecls, " imp->$setterExpressionPrefix$result");
1025 push(@implContentDecls, ", ec") if $useExceptions;
1026 push(@implContentDecls, ");\n");
1029 if ($useExceptions) {
1030 push(@implContentDecls, " if (UNLIKELY(ec))\n");
1031 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
1034 if ($svgNativeType) {
1035 if ($useExceptions) {
1036 push(@implContentDecls, " if (!ec)\n");
1037 push(@implContentDecls, " wrapper->commitChange();\n");
1039 push(@implContentDecls, " wrapper->commitChange();\n");
1041 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
1042 $implIncludes{"SVGElement.h"} = 1;
1043 push(@implContentDecls, " if (SVGElement* context = V8Proxy::svgContext(imp))\n");
1044 push(@implContentDecls, " context->svgAttributeChanged(imp->associatedAttributeName());\n");
1047 push(@implContentDecls, " return;\n");
1048 push(@implContentDecls, "}\n\n"); # end of setter
1049 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1052 sub GetFunctionTemplateCallbackName
1055 $interfaceName = shift;
1057 my $name = $function->signature->name;
1059 if ($function->signature->extendedAttributes->{"Custom"} ||
1060 $function->signature->extendedAttributes->{"V8Custom"}) {
1061 if ($function->signature->extendedAttributes->{"Custom"} &&
1062 $function->signature->extendedAttributes->{"V8Custom"}) {
1063 die "Custom and V8Custom should be mutually exclusive!"
1065 return "V8${interfaceName}::${name}Callback";
1067 return "${interfaceName}Internal::${name}Callback";
1071 sub GenerateNewFunctionTemplate
1074 $interfaceName = shift;
1077 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1078 return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
1081 sub GenerateEventListenerCallback
1083 my $implClassName = shift;
1084 my $functionName = shift;
1085 my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
1086 my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1087 my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1089 push(@implContentDecls, <<END);
1090 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1092 INC_STATS("DOM.${implClassName}.${functionName}EventListener()");
1093 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType});
1095 V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue());
1096 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex);
1098 return v8::Undefined();
1104 sub GenerateParametersCheckExpression
1106 my $numParameters = shift;
1107 my $function = shift;
1109 my @andExpression = ();
1110 push(@andExpression, "args.Length() == $numParameters");
1111 my $parameterIndex = 0;
1112 foreach $parameter (@{$function->parameters}) {
1113 last if $parameterIndex >= $numParameters;
1114 my $value = "args[$parameterIndex]";
1115 my $type = GetTypeFromSignature($parameter);
1117 # Only DOMString or wrapper types are checked.
1118 # For DOMString, Null, Undefined and any Object are accepted too, as
1119 # these are acceptable values for a DOMString argument (any Object can
1120 # be converted to a string via .toString).
1121 if ($codeGenerator->IsStringType($type)) {
1122 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
1123 } elsif ($parameter->extendedAttributes->{"Callback"}) {
1124 # For Callbacks only checks if the value is null or object.
1125 push(@andExpression, "(${value}->IsNull() || ${value}->IsObject())");
1126 } elsif (IsWrapperType($type)) {
1127 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))");
1132 my $res = join(" && ", @andExpression);
1133 $res = "($res)" if @andExpression > 1;
1137 sub GenerateFunctionParametersCheck
1139 my $function = shift;
1141 my @orExpression = ();
1142 my $numParameters = 0;
1143 foreach $parameter (@{$function->parameters}) {
1144 if ($parameter->extendedAttributes->{"Optional"}) {
1145 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1149 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1150 return join(" || ", @orExpression);
1153 sub GenerateOverloadedFunctionCallback
1155 my $function = shift;
1156 my $dataNode = shift;
1157 my $implClassName = shift;
1159 # Generate code for choosing the correct overload to call. Overloads are
1160 # chosen based on the total number of arguments passed and the type of
1161 # values passed in non-primitive argument slots. When more than a single
1162 # overload is applicable, precedence is given according to the order of
1163 # declaration in the IDL.
1165 my $name = $function->signature->name;
1166 push(@implContentDecls, <<END);
1167 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1169 INC_STATS(\"DOM.$implClassName.$name\");
1172 foreach my $overload (@{$function->{overloads}}) {
1173 my $parametersCheck = GenerateFunctionParametersCheck($overload);
1174 push(@implContentDecls, " if ($parametersCheck)\n");
1175 push(@implContentDecls, " return ${name}$overload->{overloadIndex}Callback(args);\n");
1177 push(@implContentDecls, <<END);
1178 V8Proxy::throwTypeError();
1179 return notHandledByInterceptor();
1181 push(@implContentDecls, "}\n\n");
1184 sub GenerateFunctionCallback
1186 my $function = shift;
1187 my $dataNode = shift;
1188 my $implClassName = shift;
1190 my $interfaceName = $dataNode->name;
1191 my $name = $function->signature->name;
1193 if (@{$function->{overloads}} > 1) {
1194 # Append a number to an overloaded method's name to make it unique:
1195 $name = $name . $function->{overloadIndex};
1198 # Adding and removing event listeners are not standard callback behavior,
1199 # but they are extremely consistent across the various classes that take event listeners,
1200 # so we can generate them as a "special case".
1201 if ($name eq "addEventListener") {
1202 GenerateEventListenerCallback($implClassName, "add");
1204 } elsif ($name eq "removeEventListener") {
1205 GenerateEventListenerCallback($implClassName, "remove");
1209 push(@implContentDecls, <<END);
1210 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1212 INC_STATS(\"DOM.$implClassName.$name\");
1215 my $numParameters = @{$function->parameters};
1217 my $requiresAllArguments = $function->signature->extendedAttributes->{"RequiresAllArguments"};
1218 if ($requiresAllArguments) {
1219 my $numMandatoryParams = @{$function->parameters};
1220 foreach my $param (reverse(@{$function->parameters})) {
1221 if ($param->extendedAttributes->{"Optional"}) {
1222 $numMandatoryParams--;
1227 push(@implContentDecls, " if (args.Length() < $numMandatoryParams)\n");
1228 if ($requiresAllArguments eq "Raise") {
1229 push(@implContentDecls, " return throwError(\"Not enough arguments\", V8Proxy::SyntaxError);\n");
1231 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1235 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
1237 if ($svgNativeType) {
1238 my $nativeClassName = GetNativeType($implClassName);
1239 if ($implClassName =~ /List$/) {
1240 push(@implContentDecls, " $nativeClassName imp = V8${implClassName}::toNative(args.Holder());\n");
1242 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1243 push(@implContentDecls, " $nativeClassName wrapper = V8${implClassName}::toNative(args.Holder());\n");
1244 push(@implContentDecls, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1245 push(@implContentDecls, " $svgWrappedNativeType* imp = &impInstance;\n");
1247 } elsif (!$function->signature->extendedAttributes->{"ClassMethod"}) {
1248 push(@implContentDecls, <<END);
1249 ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
1253 # Check domain security if needed
1254 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
1255 || $interfaceName eq "DOMWindow")
1256 && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1257 # We have not find real use cases yet.
1258 push(@implContentDecls, <<END);
1259 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
1260 return v8::Handle<v8::Value>();
1264 my $raisesExceptions = @{$function->raisesExceptions};
1265 if (!$raisesExceptions) {
1266 foreach my $parameter (@{$function->parameters}) {
1267 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1268 $raisesExceptions = 1;
1273 if ($raisesExceptions) {
1274 $implIncludes{"ExceptionCode.h"} = 1;
1275 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1276 push(@implContentDecls, " {\n");
1277 # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1278 # of objects (like Strings) declared later, causing compile errors. The block scope ends
1279 # right before the label 'fail:'.
1282 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1283 push(@implContentDecls, <<END);
1284 OwnPtr<ScriptArguments> scriptArguments(createScriptArguments(args, $numParameters));
1285 size_t maxStackSize = imp->shouldCaptureFullStackTrace() ? ScriptCallStack::maxCallStackSizeToCapture : 1;
1286 OwnPtr<ScriptCallStack> callStack(createScriptCallStack(maxStackSize));
1288 return v8::Undefined();
1290 $implIncludes{"ScriptArguments.h"} = 1;
1291 $implIncludes{"ScriptCallStack.h"} = 1;
1292 $implIncludes{"ScriptCallStackFactory.h"} = 1;
1294 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1295 push(@implContentDecls, <<END);
1296 if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))
1297 return v8::Handle<v8::Value>();
1302 foreach my $parameter (@{$function->parameters}) {
1303 TranslateParameter($parameter);
1305 my $parameterName = $parameter->name;
1307 # Optional callbacks should be treated differently, because they always have a default value (0),
1308 # and we can reduce the number of overloaded functions that take a different number of parameters.
1309 if ($parameter->extendedAttributes->{"Optional"} && !$parameter->extendedAttributes->{"Callback"}) {
1310 # Generate early call if there are not enough parameters.
1311 push(@implContentDecls, " if (args.Length() <= $paramIndex) {\n");
1312 my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName);
1313 push(@implContentDecls, $functionCall);
1314 push(@implContentDecls, " }\n");
1317 $implIncludes{"ExceptionCode.h"} = 1;
1318 my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1319 if ($parameter->extendedAttributes->{"Callback"}) {
1320 my $className = GetCallbackClassName($parameter->type);
1321 $implIncludes{"$className.h"} = 1;
1322 if ($parameter->extendedAttributes->{"Optional"}) {
1323 push(@implContentDecls, " RefPtr<" . $parameter->type . "> $parameterName;\n");
1324 push(@implContentDecls, " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n");
1325 push(@implContentDecls, " if (!args[$paramIndex]->IsObject())\n");
1326 push(@implContentDecls, " return throwError(TYPE_MISMATCH_ERR);\n");
1327 push(@implContentDecls, " $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n");
1328 push(@implContentDecls, " }\n");
1330 push(@implContentDecls, " if (args.Length() <= $paramIndex || !args[$paramIndex]->IsObject())\n");
1331 push(@implContentDecls, " return throwError(TYPE_MISMATCH_ERR);\n");
1332 push(@implContentDecls, " RefPtr<" . $parameter->type . "> $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n");
1334 } elsif ($parameter->type eq "SerializedScriptValue") {
1335 $implIncludes{"SerializedScriptValue.h"} = 1;
1336 push(@implContentDecls, " bool ${parameterName}DidThrow = false;\n");
1337 push(@implContentDecls, " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n");
1338 push(@implContentDecls, " if (${parameterName}DidThrow)\n");
1339 push(@implContentDecls, " return v8::Undefined();\n");
1340 } elsif (TypeCanFailConversion($parameter)) {
1341 push(@implContentDecls, " $nativeType $parameterName = " .
1342 JSValueToNative($parameter, "args[$paramIndex]") . ";\n");
1343 push(@implContentDecls, " if (UNLIKELY(!$parameterName)) {\n");
1344 push(@implContentDecls, " ec = TYPE_MISMATCH_ERR;\n");
1345 push(@implContentDecls, " goto fail;\n");
1346 push(@implContentDecls, " }\n");
1347 } elsif ($nativeType =~ /^V8Parameter/) {
1348 my $value = JSValueToNative($parameter, "args[$paramIndex]");
1349 push(@implContentDecls, " " . ConvertToV8Parameter($parameter, $nativeType, $parameterName, $value) . "\n");
1351 $implIncludes{"V8BindingMacros.h"} = 1;
1352 # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
1353 # interface type, then if the incoming value does not implement that interface, a TypeError
1354 # is thrown rather than silently passing NULL to the C++ code.
1355 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
1356 # to both strings and numbers, so do not throw TypeError if the argument is of these
1358 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1359 my $argValue = "args[$paramIndex]";
1360 my $argType = GetTypeFromSignature($parameter);
1361 if (IsWrapperType($argType)) {
1362 push(@implContentDecls, " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue)) {\n");
1363 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1364 push(@implContentDecls, " return notHandledByInterceptor();\n");
1365 push(@implContentDecls, " }\n");
1368 push(@implContentDecls, " EXCEPTION_BLOCK($nativeType, $parameterName, " .
1369 JSValueToNative($parameter, "args[$paramIndex]") . ");\n");
1372 if ($parameter->extendedAttributes->{"IsIndex"}) {
1373 push(@implContentDecls, " if (UNLIKELY($parameterName < 0)) {\n");
1374 push(@implContentDecls, " ec = INDEX_SIZE_ERR;\n");
1375 push(@implContentDecls, " goto fail;\n");
1376 push(@implContentDecls, " }\n");
1382 # Build the function call string.
1383 my $callString = GenerateFunctionCallString($function, $paramIndex, " ", $implClassName);
1384 push(@implContentDecls, "$callString");
1386 if ($raisesExceptions) {
1387 push(@implContentDecls, " }\n");
1388 push(@implContentDecls, " fail:\n");
1389 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
1390 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1393 push(@implContentDecls, "}\n\n");
1396 sub GenerateBatchedAttributeData
1398 my $dataNode = shift;
1399 my $interfaceName = $dataNode->name;
1400 my $attributes = shift;
1402 foreach my $attribute (@$attributes) {
1403 my $conditionalString = GenerateConditionalString($attribute->signature);
1404 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1405 GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1406 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
1410 sub GenerateSingleBatchedAttribute
1412 my $interfaceName = shift;
1413 my $attribute = shift;
1414 my $delimiter = shift;
1416 my $attrName = $attribute->signature->name;
1417 my $attrExt = $attribute->signature->extendedAttributes;
1419 # Attributes of type SerializedScriptValue are set in the
1420 # constructor and don't require callbacks.
1421 return if ($attribute->signature->type eq "SerializedScriptValue");
1423 my $accessControl = "v8::DEFAULT";
1424 if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1425 $accessControl = "v8::ALL_CAN_READ";
1426 } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1427 $accessControl = "v8::ALL_CAN_WRITE";
1428 } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1429 $accessControl = "v8::ALL_CAN_READ";
1430 if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1431 $accessControl .= " | v8::ALL_CAN_WRITE";
1434 if ($attrExt->{"V8DisallowShadowing"}) {
1435 $accessControl .= " | v8::PROHIBITS_OVERWRITING";
1437 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1439 my $customAccessor =
1440 $attrExt->{"Custom"} ||
1441 $attrExt->{"CustomSetter"} ||
1442 $attrExt->{"CustomGetter"} ||
1443 $attrExt->{"V8Custom"} ||
1444 $attrExt->{"V8CustomSetter"} ||
1445 $attrExt->{"V8CustomGetter"} ||
1447 if ($customAccessor eq 1) {
1448 # use the naming convension, interface + (capitalize) attr name
1449 $customAccessor = $interfaceName . "::" . $attrName;
1454 my $propAttr = "v8::None";
1455 my $hasCustomSetter = 0;
1458 if ($attrExt->{"DontEnum"}) {
1459 $propAttr .= " | v8::DontEnum";
1461 if ($attrExt->{"V8DisallowShadowing"}) {
1462 $propAttr .= " | v8::DontDelete";
1465 my $on_proto = "0 /* on instance */";
1466 my $data = "0 /* no data */";
1469 if ($attribute->signature->type =~ /Constructor$/) {
1470 my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1471 $constructorType =~ s/Constructor$//;
1472 $implIncludes{"V8${constructorType}.h"} = 1;
1473 if ($customAccessor) {
1474 $getter = "V8${customAccessor}AccessorGetter";
1476 $data = "&V8${constructorType}::info";
1477 $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1480 $propAttr = "v8::ReadOnly";
1483 # Default Getter and Setter
1484 $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1485 $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1488 if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1489 $hasCustomSetter = 1;
1490 $setter = "V8${customAccessor}AccessorSetter";
1494 if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1495 $getter = "V8${customAccessor}AccessorGetter";
1500 if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1502 # Handle the special case of window.top being marked as Replaceable.
1503 # FIXME: Investigate whether we could treat window.top as replaceable
1504 # and allow shadowing without it being a security hole.
1505 if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1506 $propAttr .= " | v8::ReadOnly";
1510 # Read only attributes
1511 if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1515 # An accessor can be installed on the proto
1516 if ($attrExt->{"v8OnProto"}) {
1517 $on_proto = "1 /* on proto */";
1520 my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1521 "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1523 push(@implContent, $indent . " \/\/ $commentInfo\n");
1524 push(@implContent, $indent . " {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
1527 sub GenerateImplementationIndexer
1529 my $dataNode = shift;
1530 my $indexer = shift;
1531 my $interfaceName = $dataNode->name;
1533 # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files.
1534 my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
1535 my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1537 # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
1538 if ($interfaceName eq "HTMLOptionsCollection") {
1541 # FIXME: If the parent interface of $dataNode already has
1542 # HasIndexGetter, we don't need to handle the getter here.
1543 if ($interfaceName eq "WebKitCSSTransformValue") {
1547 # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
1548 # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
1549 # simplistic, mirrored indexer handling in addition to named property handling.
1550 my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
1551 if ($isSpecialCase) {
1553 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
1554 $hasCustomSetter = 1;
1562 $implIncludes{"V8Collection.h"} = 1;
1564 my $indexerType = $indexer ? $indexer->type : 0;
1566 # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
1567 if ($interfaceName eq "WebKitCSSKeyframesRule") {
1568 $indexerType = "WebKitCSSKeyframeRule";
1571 if ($indexerType && !$hasCustomSetter) {
1572 if ($indexerType eq "DOMString") {
1573 my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
1574 if ($conversion && $conversion eq "Null") {
1575 push(@implContent, <<END);
1576 setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
1579 push(@implContent, <<END);
1580 setCollectionStringIndexedGetter<${interfaceName}>(desc);
1584 push(@implContent, <<END);
1585 setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
1587 # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
1588 $implIncludes{"V8${indexerType}.h"} = 1;
1594 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1595 my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
1596 my $setOn = "Instance";
1598 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1599 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1600 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1602 if ($interfaceName eq "DOMWindow") {
1603 $setOn = "Prototype";
1607 push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
1608 push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
1609 push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
1610 push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
1611 push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
1612 push(@implContent, ");\n");
1615 sub GenerateImplementationNamedPropertyGetter
1617 my $dataNode = shift;
1618 my $namedPropertyGetter = shift;
1619 my $interfaceName = $dataNode->name;
1620 my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1622 # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
1623 # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
1624 if ($interfaceName eq "HTMLOptionsCollection") {
1625 $interfaceName = "HTMLCollection";
1626 $hasCustomGetter = 1;
1629 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
1630 $hasCustomGetter = 1;
1633 if ($interfaceName eq "HTMLDocument") {
1634 $hasCustomGetter = 0;
1637 my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter;
1642 if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) {
1643 $implIncludes{"V8Collection.h"} = 1;
1644 my $type = $namedPropertyGetter->type;
1645 push(@implContent, <<END);
1646 setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
1651 my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
1652 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1653 my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
1654 my $setOn = "Instance";
1656 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1657 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1658 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1660 if ($interfaceName eq "DOMWindow") {
1661 $setOn = "Prototype";
1666 push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
1667 push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
1668 # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
1669 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyQuery, " : "0, ");
1670 push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
1671 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
1672 push(@implContent, ");\n");
1675 sub GenerateImplementationCustomCall
1677 my $dataNode = shift;
1678 my $interfaceName = $dataNode->name;
1679 my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
1681 # FIXME: Remove hard-coded HTMLOptionsCollection reference.
1682 if ($interfaceName eq "HTMLOptionsCollection") {
1683 $interfaceName = "HTMLCollection";
1687 if ($hasCustomCall) {
1688 push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
1692 sub GenerateImplementationMasqueradesAsUndefined
1694 my $dataNode = shift;
1695 if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
1697 push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n");
1701 sub GenerateImplementation
1704 my $dataNode = shift;
1705 my $interfaceName = $dataNode->name;
1706 my $visibleInterfaceName = GetVisibleInterfaceName($interfaceName);
1707 my $className = "V8$interfaceName";
1708 my $implClassName = $interfaceName;
1709 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1711 # - Add default header template
1712 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
1714 $implIncludes{"RuntimeEnabledFeatures.h"} = 1;
1715 $implIncludes{"V8Proxy.h"} = 1;
1716 $implIncludes{"V8Binding.h"} = 1;
1717 $implIncludes{"V8BindingState.h"} = 1;
1718 $implIncludes{"V8DOMWrapper.h"} = 1;
1719 $implIncludes{"V8IsolatedContext.h"} = 1;
1721 AddIncludesForType($interfaceName);
1723 my $toActive = IsActiveDomType($interfaceName) ? "${className}::toActiveDOMObject" : "0";
1725 push(@implContentDecls, "namespace WebCore {\n\n");
1726 push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive} };\n\n");
1727 push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1728 push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1730 my $hasConstructors = 0;
1731 my $serializedAttribute;
1732 # Generate property accessors for attributes.
1733 for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1734 $attribute = @{$dataNode->attributes}[$index];
1735 $attrName = $attribute->signature->name;
1736 $attrType = $attribute->signature->type;
1738 # Generate special code for the constructor attributes.
1739 if ($attrType =~ /Constructor$/) {
1740 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1741 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1742 $hasConstructors = 1;
1747 if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1748 $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1751 # Attributes of type SerializedScriptValue are set in the
1752 # constructor and don't require callbacks.
1753 if ($attrType eq "SerializedScriptValue") {
1754 die "Only one attribute of type SerializedScriptValue supported" if $serializedAttribute;
1755 $implIncludes{"SerializedScriptValue.h"} = 1;
1756 $serializedAttribute = $attribute;
1760 # Do not generate accessor if this is a custom attribute. The
1761 # call will be forwarded to a hand-written accessor
1763 if ($attribute->signature->extendedAttributes->{"Custom"} ||
1764 $attribute->signature->extendedAttributes->{"V8Custom"}) {
1768 # Generate the accessor.
1769 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1770 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1771 GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
1773 if (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
1774 !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
1775 !$attribute->signature->extendedAttributes->{"Replaceable"} &&
1776 $attribute->type !~ /^readonly/ &&
1777 !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1778 GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
1782 if ($hasConstructors) {
1783 GenerateConstructorGetter($implClassName);
1786 $codeGenerator->LinkOverloadedFunctions($dataNode);
1789 my $namedPropertyGetter;
1790 # Generate methods for functions.
1791 foreach my $function (@{$dataNode->functions}) {
1792 if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) {
1793 GenerateFunctionCallback($function, $dataNode, $implClassName);
1794 if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
1795 GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName);
1799 if ($function->signature->name eq "item") {
1800 $indexer = $function->signature;
1803 if ($function->signature->name eq "namedItem") {
1804 $namedPropertyGetter = $function->signature;
1807 # If the function does not need domain security check, we need to
1808 # generate an access getter that returns different function objects
1809 # for different calling context.
1810 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1811 GenerateDomainSafeFunctionGetter($function, $implClassName);
1816 my $attributes = $dataNode->attributes;
1818 # For the DOMWindow interface we partition the attributes into the
1819 # ones that disallows shadowing and the rest.
1820 my @disallowsShadowing;
1821 # Also separate out attributes that are enabled at runtime so we can process them specially.
1822 my @enabledAtRuntime;
1824 foreach my $attribute (@$attributes) {
1826 if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1827 push(@disallowsShadowing, $attribute);
1828 } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1829 push(@enabledAtRuntime, $attribute);
1831 push(@normal, $attribute);
1834 $attributes = \@normal;
1835 # Put the attributes that disallow shadowing on the shadow object.
1836 if (@disallowsShadowing) {
1837 push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n");
1838 GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1839 push(@implContent, "};\n");
1842 my $has_attributes = 0;
1844 $has_attributes = 1;
1845 push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n");
1846 GenerateBatchedAttributeData($dataNode, $attributes);
1847 push(@implContent, "};\n");
1850 # Setup table of standard callback functions
1853 foreach my $function (@{$dataNode->functions}) {
1854 # Only one table entry is needed for overloaded methods:
1855 next if $function->{overloadIndex} > 1;
1857 my $attrExt = $function->signature->extendedAttributes;
1858 # Don't put any nonstandard functions into this table:
1859 if ($attrExt->{"V8OnInstance"}) {
1862 if ($attrExt->{"ClassMethod"}) {
1865 if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1868 if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1869 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1872 if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1875 if (!$has_callbacks) {
1877 push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n");
1879 my $name = $function->signature->name;
1880 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1881 push(@implContent, <<END);
1882 {"$name", $callback},
1886 push(@implContent, "};\n") if $has_callbacks;
1889 my $has_constants = 0;
1890 if (@{$dataNode->constants}) {
1892 push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n");
1894 foreach my $constant (@{$dataNode->constants}) {
1895 my $name = $constant->name;
1896 my $value = $constant->value;
1897 # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
1898 # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we
1899 # handled this here, and converted it to a -1 constant in the c++ output.
1900 push(@implContent, <<END);
1901 {"${name}", static_cast<signed int>($value)},
1904 if ($has_constants) {
1905 push(@implContent, "};\n");
1906 push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
1909 push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
1911 # In namespace WebCore, add generated implementation for 'CanBeConstructed'.
1912 if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"} && !$dataNode->extendedAttributes->{"V8CustomConstructor"}) {
1913 my $v8ConstructFunction;
1914 my $callWith = $dataNode->extendedAttributes->{"CallWith"};
1915 if ($callWith and $callWith eq "ScriptExecutionContext") {
1916 $v8ConstructFunction = "constructDOMObjectWithScriptExecutionContext";
1918 $v8ConstructFunction = "constructDOMObject";
1920 push(@implContent, <<END);
1921 v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args)
1923 INC_STATS("DOM.${interfaceName}.Contructor");
1924 return V8Proxy::${v8ConstructFunction}<$interfaceName>(args, &info);
1929 my $access_check = "";
1930 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
1931 $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));";
1934 # For the DOMWindow interface, generate the shadow object template
1935 # configuration method.
1936 if ($implClassName eq "DOMWindow") {
1937 push(@implContent, <<END);
1938 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
1940 batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, sizeof(shadowAttrs) / sizeof(*shadowAttrs));
1942 // Install a security handler with V8.
1943 templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info));
1944 templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
1950 # find the super descriptor
1951 my $parentClassTemplate = "";
1952 foreach (@{$dataNode->parents}) {
1953 my $parent = $codeGenerator->StripModule($_);
1954 if ($parent eq "EventTarget") { next; }
1955 $implIncludes{"V8${parent}.h"} = 1;
1956 $parentClassTemplate = "V8" . $parent . "::GetTemplate()";
1959 if (!$parentClassTemplate) {
1960 $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
1963 # Generate the template configuration method
1964 push(@implContent, <<END);
1965 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc)
1967 v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount,
1969 # Set up our attributes if we have them
1970 if ($has_attributes) {
1971 push(@implContent, <<END);
1972 ${interfaceName}Attrs, sizeof(${interfaceName}Attrs) / sizeof(*${interfaceName}Attrs),
1975 push(@implContent, <<END);
1980 if ($has_callbacks) {
1981 push(@implContent, <<END);
1982 ${interfaceName}Callbacks, sizeof(${interfaceName}Callbacks) / sizeof(*${interfaceName}Callbacks));
1985 push(@implContent, <<END);
1990 if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
1991 push(@implContent, <<END);
1992 desc->SetCallHandler(V8${interfaceName}::constructorCallback);
1996 if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
1997 push(@implContent, <<END);
1998 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
1999 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
2003 push(@implContent, " $access_check\n");
2005 # Setup the enable-at-runtime attrs if we have them
2006 foreach my $runtime_attr (@enabledAtRuntime) {
2007 my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
2008 my $conditionalString = GenerateConditionalString($runtime_attr->signature);
2009 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2010 push(@implContent, " if (${enable_function}()) {\n");
2011 push(@implContent, " static const BatchedAttribute attrData =\\\n");
2012 GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " ");
2013 push(@implContent, <<END);
2014 configureAttribute(instance, proto, attrData);
2017 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2020 GenerateImplementationIndexer($dataNode, $indexer);
2021 GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
2022 GenerateImplementationCustomCall($dataNode);
2023 GenerateImplementationMasqueradesAsUndefined($dataNode);
2025 # Define our functions with Set() or SetAccessor()
2026 $total_functions = 0;
2027 foreach my $function (@{$dataNode->functions}) {
2028 # Only one accessor is needed for overloaded methods:
2029 next if $function->{overloadIndex} > 1;
2032 my $attrExt = $function->signature->extendedAttributes;
2033 my $name = $function->signature->name;
2035 my $property_attributes = "v8::DontDelete";
2036 if ($attrExt->{"DontEnum"}) {
2037 $property_attributes .= " | v8::DontEnum";
2039 if ($attrExt->{"V8ReadOnly"}) {
2040 $property_attributes .= " | v8::ReadOnly";
2043 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2045 my $template = "proto";
2046 if ($attrExt->{"V8OnInstance"}) {
2047 $template = "instance";
2049 if ($attrExt->{"ClassMethod"}) {
2053 my $conditional = "";
2054 if ($attrExt->{"EnabledAtRuntime"}) {
2055 # Only call Set()/SetAccessor() if this method should be enabled
2056 $enable_function = GetRuntimeEnableFunctionName($function->signature);
2057 $conditional = "if (${enable_function}())\n ";
2060 if ($attrExt->{"DoNotCheckDomainSecurity"} &&
2061 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
2062 # Mark the accessor as ReadOnly and set it on the proto object so
2063 # it can be shadowed. This is really a hack to make it work.
2064 # There are several sceneria to call into the accessor:
2065 # 1) from the same domain: "window.open":
2066 # the accessor finds the DOM wrapper in the proto chain;
2067 # 2) from the same domain: "window.__proto__.open":
2068 # the accessor will NOT find a DOM wrapper in the prototype chain
2069 # 3) from another domain: "window.open":
2070 # the access find the DOM wrapper in the prototype chain
2071 # "window.__proto__.open" from another domain will fail when
2072 # accessing '__proto__'
2074 # The solution is very hacky and fragile, it really needs to be replaced
2075 # by a better solution.
2076 $property_attributes .= " | v8::ReadOnly";
2077 push(@implContent, <<END);
2080 ${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));
2086 my $signature = "defaultSignature";
2087 if ($attrExt->{"V8DoNotCheckSignature"} || $attrExt->{"ClassMethod"}) {
2088 $signature = "v8::Local<v8::Signature>()";
2091 if (RequiresCustomSignature($function)) {
2092 $signature = "${name}Signature";
2093 push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function));
2096 # Normal function call is a template
2097 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2099 if ($property_attributes eq "v8::DontDelete") {
2100 $property_attributes = "";
2102 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2105 if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2106 # Standard type of callback, already created in the batch, so skip it here.
2110 push(@implContent, <<END);
2111 ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);
2116 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
2118 if ($has_constants) {
2119 push(@implContent, <<END);
2120 batchConfigureConstants(desc, proto, ${interfaceName}Consts, sizeof(${interfaceName}Consts) / sizeof(*${interfaceName}Consts));
2125 if ($interfaceName eq "DOMWindow") {
2126 push(@implContent, <<END);
2128 proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2129 desc->SetHiddenPrototype(true);
2130 instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2131 // Set access check callbacks, but turned off initially.
2132 // When a context is detached from a frame, turn on the access check.
2133 // Turning on checks also invalidates inline caches of the object.
2134 instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false);
2137 if ($interfaceName eq "HTMLDocument") {
2138 push(@implContent, <<END);
2139 desc->SetHiddenPrototype(true);
2142 if ($interfaceName eq "Location") {
2143 push(@implContent, <<END);
2145 // For security reasons, these functions are on the instance instead
2146 // of on the prototype object to ensure that they cannot be overwritten.
2147 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));
2148 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));
2149 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));
2153 my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
2154 push(@implContent, <<END);
2156 // Custom toString template
2157 desc->Set(getToStringName(), getToStringTemplate());
2161 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate()
2163 static v8::Persistent<v8::FunctionTemplate> ${className}RawCache = createRawTemplate();
2164 return ${className}RawCache;
2167 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()\
2169 static v8::Persistent<v8::FunctionTemplate> ${className}Cache = Configure${className}Template(GetRawTemplate());
2170 return ${className}Cache;
2173 bool ${className}::HasInstance(v8::Handle<v8::Value> value)
2175 return GetRawTemplate()->HasInstance(value);
2180 if (IsActiveDomType($interfaceName)) {
2181 # MessagePort is handled like an active dom object even though it doesn't inherit
2182 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
2183 my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
2184 push(@implContent, <<END);
2185 ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object)
2187 return ${returnValue};
2192 if ($implClassName eq "DOMWindow") {
2193 push(@implContent, <<END);
2194 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
2196 static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
2197 if (V8DOMWindowShadowObjectCache.IsEmpty()) {
2198 V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
2199 ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
2201 return V8DOMWindowShadowObjectCache;
2206 GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType, $serializedAttribute);
2208 push(@implContent, <<END);
2210 void ${className}::derefObject(void* object)
2214 if (IsRefPtrType($interfaceName)) {
2215 push(@implContent, <<END);
2216 static_cast<${nativeType}*>(object)->deref();
2220 push(@implContent, <<END);
2223 } // namespace WebCore
2226 my $conditionalString = GenerateConditionalString($dataNode);
2227 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2229 # We've already added the header for this file in implFixedHeader, so remove
2230 # it from implIncludes to ensure we don't #include it twice.
2231 delete $implIncludes{"${className}.h"};
2234 sub GenerateHeaderContentHeader
2236 my $dataNode = shift;
2237 my $className = "V8" . $dataNode->name;
2238 my $conditionalString = GenerateConditionalString($dataNode);
2240 my @headerContentHeader = split("\r", $headerTemplate);
2242 push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
2243 push(@headerContentHeader, "\n#ifndef ${className}" . "_h");
2244 push(@headerContentHeader, "\n#define ${className}" . "_h\n\n");
2245 return @headerContentHeader;
2248 sub GenerateImplementationContentHeader
2250 my $dataNode = shift;
2251 my $className = "V8" . $dataNode->name;
2252 my $conditionalString = GenerateConditionalString($dataNode);
2254 my @implContentHeader = split("\r", $headerTemplate);
2256 push(@implContentHeader, "\n#include \"config.h\"\n");
2257 push(@implContentHeader, "#include \"${className}.h\"\n\n");
2258 push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
2259 return @implContentHeader;
2262 sub GenerateCallbackHeader
2265 my $dataNode = shift;
2267 my $interfaceName = $dataNode->name;
2268 my $className = "V8$interfaceName";
2271 # - Add default header template
2272 push(@headerContent, GenerateHeaderContentHeader($dataNode));
2274 my @unsortedIncludes = ();
2275 push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\"");
2276 push(@unsortedIncludes, "#include \"$interfaceName.h\"");
2277 push(@unsortedIncludes, "#include \"WorldContextHandle.h\"");
2278 push(@unsortedIncludes, "#include <v8.h>");
2279 push(@unsortedIncludes, "#include <wtf/Forward.h>");
2280 push(@headerContent, join("\n", sort @unsortedIncludes));
2282 push(@headerContent, "\n\nnamespace WebCore {\n\n");
2283 push(@headerContent, "class ScriptExecutionContext;\n\n");
2284 push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
2286 push(@headerContent, <<END);
2288 static PassRefPtr<${className}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
2290 ASSERT(value->IsObject());
2292 return adoptRef(new ${className}(value->ToObject(), context));
2295 virtual ~${className}();
2300 my $numFunctions = @{$dataNode->functions};
2301 if ($numFunctions > 0) {
2302 push(@headerContent, " // Functions\n");
2303 foreach my $function (@{$dataNode->functions}) {
2304 my @params = @{$function->parameters};
2305 if (!$function->signature->extendedAttributes->{"Custom"} &&
2306 !(GetNativeType($function->signature->type) eq "bool")) {
2307 push(@headerContent, " COMPILE_ASSERT(false)");
2310 push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
2313 foreach my $param (@params) {
2314 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2316 push(@headerContent, join(", ", @args));
2317 push(@headerContent, ");\n");
2321 push(@headerContent, <<END);
2324 ${className}(v8::Local<v8::Object>, ScriptExecutionContext*);
2326 v8::Persistent<v8::Object> m_callback;
2327 WorldContextHandle m_worldContext;
2332 push(@headerContent, "}\n\n");
2333 push(@headerContent, "#endif // $className" . "_h\n\n");
2335 my $conditionalString = GenerateConditionalString($dataNode);
2336 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
2339 sub GenerateCallbackImplementation
2342 my $dataNode = shift;
2343 my $interfaceName = $dataNode->name;
2344 my $className = "V8$interfaceName";
2346 # - Add default header template
2347 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2349 $implIncludes{"ScriptExecutionContext.h"} = 1;
2350 $implIncludes{"V8CustomVoidCallback.h"} = 1;
2351 $implIncludes{"V8Proxy.h"} = 1;
2353 push(@implContent, "#include <wtf/Assertions.h>\n\n");
2354 push(@implContent, "namespace WebCore {\n\n");
2355 push(@implContent, <<END);
2356 ${className}::${className}(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
2357 : ActiveDOMCallback(context)
2358 , m_callback(v8::Persistent<v8::Object>::New(callback))
2359 , m_worldContext(UseCurrentWorld)
2363 ${className}::~${className}()
2365 m_callback.Dispose();
2371 my $numFunctions = @{$dataNode->functions};
2372 if ($numFunctions > 0) {
2373 push(@implContent, "// Functions\n");
2374 foreach my $function (@{$dataNode->functions}) {
2375 my @params = @{$function->parameters};
2376 if ($function->signature->extendedAttributes->{"Custom"} ||
2377 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
2381 AddIncludesForType($function->signature->type);
2382 push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(");
2385 foreach my $param (@params) {
2386 AddIncludesForType($param->type);
2387 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2389 push(@implContent, join(", ", @args));
2391 push(@implContent, ")\n");
2392 push(@implContent, "{\n");
2393 push(@implContent, " if (!canInvokeCallback())\n");
2394 push(@implContent, " return true;\n\n");
2395 push(@implContent, " v8::HandleScope handleScope;\n\n");
2396 push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n");
2397 push(@implContent, " if (v8Context.IsEmpty())\n");
2398 push(@implContent, " return true;\n\n");
2399 push(@implContent, " v8::Context::Scope scope(v8Context);\n\n");
2402 foreach my $param (@params) {
2403 my $paramName = $param->name;
2404 push(@implContent, " v8::Handle<v8::Value> ${paramName}Handle = toV8(${paramName});\n");
2405 push(@implContent, " if (${paramName}Handle.IsEmpty()) {\n");
2406 push(@implContent, " CRASH();\n");
2407 push(@implContent, " return true;\n");
2408 push(@implContent, " }\n");
2409 push(@args, " ${paramName}Handle");
2412 push(@implContent, "\n v8::Handle<v8::Value> argv[] = {\n");
2413 push(@implContent, join(",\n", @args));
2414 push(@implContent, "\n };\n\n");
2415 push(@implContent, " bool callbackReturnValue = false;\n");
2416 push(@implContent, " return !invokeCallback(m_callback, " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
2417 push(@implContent, "}\n");
2421 push(@implContent, "\n} // namespace WebCore\n\n");
2423 my $conditionalString = GenerateConditionalString($dataNode);
2424 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2427 sub GenerateToV8Converters
2429 my $dataNode = shift;
2430 my $interfaceName = shift;
2431 my $className = shift;
2432 my $nativeType = shift;
2433 my $serializedAttribute = shift;
2435 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
2436 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
2437 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
2439 push(@implContent, <<END);
2441 v8::Handle<v8::Object> ${className}::wrapSlow(${nativeType}* impl)
2443 v8::Handle<v8::Object> wrapper;
2447 if (IsNodeSubType($dataNode)) {
2448 push(@implContent, <<END);
2449 if (impl->document()) {
2450 proxy = V8Proxy::retrieve(impl->document()->frame());
2451 if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl)) {
2452 if (proxy->windowShell()->initContextIfNeeded()) {
2453 // initContextIfNeeded may have created a wrapper for the object, retry from the start.
2454 return ${className}::wrap(impl);
2462 if (IsNodeSubType($dataNode)) {
2463 push(@implContent, <<END);
2465 v8::Handle<v8::Context> context;
2467 context = proxy->context();
2469 // Enter the node's context and create the wrapper in that context.
2470 if (!context.IsEmpty())
2475 push(@implContent, <<END);
2476 wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl);
2478 if (IsNodeSubType($dataNode)) {
2479 push(@implContent, <<END);
2480 // Exit the node's context if it was entered.
2481 if (!context.IsEmpty())
2486 push(@implContent, <<END);
2487 if (wrapper.IsEmpty())
2490 push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName);
2492 # Eagerly deserialize attributes of type SerializedScriptValue
2493 # while we're in the right context.
2494 if ($serializedAttribute) {
2495 die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue";
2496 my $attrName = $serializedAttribute->signature->name;
2497 my $attrAttr = "v8::DontDelete";
2498 if ($serializedAttribute->type =~ /^readonly/) {
2499 $attrAttr .= " | v8::ReadOnly";
2501 $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)";
2502 my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
2503 push(@implContent, <<END);
2504 SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}());
2508 if ($domMapFunction) {
2509 push(@implContent, <<END);
2510 ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper));
2514 push(@implContent, <<END);
2520 sub HasCustomToV8Implementation {
2521 # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)?
2523 $interfaceName = shift;
2525 # We generate a custom converter (but JSC doesn't) for the following:
2526 return 1 if $interfaceName eq "CSSStyleSheet";
2527 return 1 if $interfaceName eq "CanvasPixelArray";
2528 return 1 if $interfaceName eq "DOMStringMap";
2529 return 1 if $interfaceName eq "DOMWindow";
2530 return 1 if $interfaceName eq "DOMTokenList";
2531 return 1 if $interfaceName eq "Element";
2532 return 1 if $interfaceName eq "HTMLDocument";
2533 return 1 if $interfaceName eq "HTMLElement";
2534 return 1 if $interfaceName eq "Location";
2535 return 1 if $interfaceName eq "NamedNodeMap";
2536 return 1 if $interfaceName eq "SVGDocument";
2537 return 1 if $interfaceName eq "SVGElement";
2538 return 1 if $interfaceName eq "ScriptProfile";
2539 return 1 if $interfaceName eq "ScriptProfileNode";
2540 return 1 if $interfaceName eq "WorkerContext";
2541 # We don't generate a custom converter (but JSC does) for the following:
2542 return 0 if $interfaceName eq "AbstractWorker";
2543 return 0 if $interfaceName eq "CanvasRenderingContext";
2544 return 0 if $interfaceName eq "ImageData";
2545 return 0 if $interfaceName eq "SVGElementInstance";
2547 # For everything else, do what JSC does.
2548 return $dataNode->extendedAttributes->{"CustomToJS"};
2551 sub GetDomMapFunction
2553 my $dataNode = shift;
2555 return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
2556 return "getDOMNodeMap()" if ($dataNode && IsNodeSubType($dataNode));
2557 # Only use getDOMSVGObjectWithContextMap() for non-node svg objects
2558 return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/ and not $codeGenerator->IsSVGTypeNeedingTearOff($type) and not $codeGenerator->IsSVGAnimatedType($type);
2559 return "" if $type eq "DOMImplementation";
2560 return "getActiveDOMObjectMap()" if IsActiveDomType($type);
2561 return "getDOMObjectMap()";
2566 # FIXME: Consider making this an .idl attribute.
2568 return 1 if $type eq "EventSource";
2569 return 1 if $type eq "MessagePort";
2570 return 1 if $type eq "XMLHttpRequest";
2571 return 1 if $type eq "WebSocket";
2572 return 1 if $type eq "Worker";
2573 return 1 if $type eq "SharedWorker";
2574 return 1 if $type eq "IDBRequest";
2575 return 1 if $type eq "FileReader";
2576 return 1 if $type eq "FileWriter";
2577 return 1 if $type eq "FileWriterSync";
2581 sub GetNativeTypeForConversions
2583 my $dataNode = shift;
2586 $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->IsSVGTypeNeedingTearOff($type);
2590 sub GenerateFunctionCallString()
2592 my $function = shift;
2593 my $numberOfParameters = shift;
2595 my $implClassName = shift;
2597 my $name = $function->signature->name;
2598 my $returnType = GetTypeFromSignature($function->signature);
2599 my $nativeReturnType = GetNativeType($returnType, 0);
2602 my $isSVGTearOffType = ($codeGenerator->IsSVGTypeNeedingTearOff($returnType) and not $implClassName =~ /List$/);
2603 $nativeReturnType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType;
2605 if ($function->signature->extendedAttributes->{"v8implname"}) {
2606 $name = $function->signature->extendedAttributes->{"v8implname"};
2609 if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
2610 $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
2613 my $functionString = "imp->${name}(";
2614 if ($function->signature->extendedAttributes->{"ClassMethod"}) {
2615 $functionString = "${implClassName}::${name}(";
2619 my $hasScriptState = 0;
2621 my $callWith = $function->signature->extendedAttributes->{"CallWith"};
2623 my $callWithArg = "COMPILE_ASSERT(false)";
2624 if ($callWith eq "DynamicFrame") {
2625 $result .= $indent . "Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext();\n";
2626 $result .= $indent . "if (!enteredFrame)\n";
2627 $result .= $indent . " return v8::Undefined();\n";
2628 $callWithArg = "enteredFrame";
2629 } elsif ($callWith eq "ScriptState") {
2630 $result .= $indent . "EmptyScriptState state;\n";
2631 $callWithArg = "&state";
2632 $hasScriptState = 1;
2633 } elsif ($callWith eq "ScriptExecutionContext") {
2634 $result .= $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n";
2635 $result .= $indent . "if (!scriptContext)\n";
2636 $result .= $indent . " return v8::Undefined();\n";
2637 $callWithArg = "scriptContext";
2639 $functionString .= ", " if $index;
2640 $functionString .= $callWithArg;
2642 $numberOfParameters++
2645 foreach my $parameter (@{$function->parameters}) {
2646 if ($index eq $numberOfParameters) {
2649 $functionString .= ", " if $index;
2650 my $paramName = $parameter->name;
2651 my $paramType = $parameter->type;
2653 if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
2654 $functionString .= "$paramName.get()";
2655 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($parameter->type) and not $implClassName =~ /List$/) {
2656 $functionString .= "$paramName->propertyReference()";
2657 $result .= $indent . "if (!$paramName) {\n";
2658 $result .= $indent . " V8Proxy::setDOMException(WebCore::TYPE_MISMATCH_ERR);\n";
2659 $result .= $indent . " return v8::Handle<v8::Value>();\n";
2660 $result .= $indent . "}\n";
2661 } elsif ($parameter->type eq "SVGMatrix" and $implClassName eq "SVGTransformList") {
2662 $functionString .= "$paramName.get()";
2664 $functionString .= $paramName;
2669 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
2670 $functionString .= ", " if $index;
2671 $functionString .= "scriptArguments.release(), callStack.release()";
2675 if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
2676 $functionString .= ", " if $index;
2677 # FIXME: We need to pass DOMWrapperWorld as a parameter.
2678 # See http://trac.webkit.org/changeset/54182
2679 $functionString .= "processingUserGesture()";
2683 if (@{$function->raisesExceptions}) {
2684 $functionString .= ", " if $index;
2685 $functionString .= "ec";
2688 $functionString .= ")";
2690 my $return = "result";
2691 my $returnIsRef = IsRefPtrType($returnType);
2693 if ($returnType eq "void") {
2694 $result .= $indent . "$functionString;\n";
2695 } elsif ($hasScriptState or @{$function->raisesExceptions}) {
2696 $result .= $indent . $nativeReturnType . " result = $functionString;\n";
2698 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
2699 $return = $functionString;
2702 if ($implClassName eq "SVGTransformList" and IsRefPtrType($returnType)) {
2703 $return = "WTF::getPtr(" . $return . ")";
2707 if (@{$function->raisesExceptions}) {
2708 $result .= $indent . "if (UNLIKELY(ec))\n";
2709 $result .= $indent . " goto fail;\n";
2712 if ($hasScriptState) {
2713 $result .= $indent . "if (state.hadException())\n";
2714 $result .= $indent . " return throwError(state.exception());\n"
2717 if ($isSVGTearOffType) {
2718 $implIncludes{"V8$returnType.h"} = 1;
2719 $implIncludes{"SVGPropertyTearOff.h"} = 1;
2720 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($returnType);
2721 $result .= $indent . "return toV8(WTF::getPtr(${svgNativeType}::create($return)));\n";
2725 my $generatedSVGContextRetrieval = 0;
2726 # If the return type needs an SVG context, output it
2727 if (IsSVGTypeNeedingContextParameter($returnType)) {
2728 $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
2729 $generatedSVGContextRetrieval = 1;
2732 if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
2733 if (!$generatedSVGContextRetrieval) {
2734 $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2735 $generatedSVGContextRetrieval = 1;
2738 $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
2739 $implIncludes{"SVGElement.h"} = 1;
2742 # If the implementing class is a POD type, commit changes
2743 if ($codeGenerator->IsSVGTypeNeedingTearOff($implClassName) and not $implClassName =~ /List$/) {
2744 $result .= $indent . "wrapper->commitChange();\n";
2747 $return .= ".release()" if ($returnIsRef);
2748 $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
2754 sub GetTypeFromSignature
2756 my $signature = shift;
2758 return $codeGenerator->StripModule($signature->type);
2762 sub GetNativeTypeFromSignature
2764 my $signature = shift;
2765 my $parameterIndex = shift;
2767 my $type = GetTypeFromSignature($signature);
2769 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
2770 # Special-case index arguments because we need to check that they aren't < 0.
2774 $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
2776 if ($parameterIndex >= 0 && $type eq "V8Parameter") {
2778 if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
2779 $mode = "WithUndefinedOrNullCheck";
2780 } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"}) {
2781 $mode = "WithNullCheck";
2793 return 0 if $type eq "boolean";
2794 return 0 if $type eq "float";
2795 return 0 if $type eq "int";
2796 return 0 if $type eq "Date";
2797 return 0 if $type eq "DOMString";
2798 return 0 if $type eq "double";
2799 return 0 if $type eq "short";
2800 return 0 if $type eq "long";
2801 return 0 if $type eq "unsigned";
2802 return 0 if $type eq "unsigned long";
2803 return 0 if $type eq "unsigned short";
2811 my $isParameter = shift;
2813 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
2814 if ($svgNativeType) {
2815 if ($svgNativeType =~ /List$/) {
2816 return "${svgNativeType}*";
2818 return "RefPtr<${svgNativeType} >";
2822 if ($type eq "float" or $type eq "double") {
2826 return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
2827 return "int" if $type eq "int";
2828 return "int" if $type eq "short" or $type eq "unsigned short";
2829 return "unsigned" if $type eq "unsigned long";
2830 return "int" if $type eq "long";
2831 return "long long" if $type eq "long long";
2832 return "unsigned long long" if $type eq "unsigned long long";
2833 return "bool" if $type eq "boolean";
2834 return "String" if $type eq "DOMString";
2835 return "Range::CompareHow" if $type eq "CompareHow";
2836 return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
2837 return "DOMTimeStamp" if $type eq "DOMTimeStamp";
2838 return "unsigned" if $type eq "unsigned int";
2839 return "Node*" if $type eq "EventTarget" and $isParameter;
2840 return "double" if $type eq "Date";
2841 return "ScriptValue" if $type eq "DOMObject";
2843 return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack?
2846 return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
2848 return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
2850 return "RefPtr<IDBKey>" if $type eq "IDBKey";
2852 # necessary as resolvers could be constructed on fly.
2853 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
2855 return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
2857 # Default, assume native type is a pointer with same type name as idl type
2861 sub GetNativeTypeForCallbacks
2864 return "const String&" if $type eq "DOMString";
2866 # Callbacks use raw pointers, so pass isParameter = 1
2867 return GetNativeType($type, 1);
2870 sub TranslateParameter
2872 my $signature = shift;
2874 # The IDL uses some pseudo-types which don't really exist.
2875 if ($signature->type eq "TimeoutHandler") {
2876 $signature->type("DOMString");
2880 sub TypeCanFailConversion
2882 my $signature = shift;
2884 my $type = GetTypeFromSignature($signature);
2886 $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
2887 return 1 if $type eq "Attr";
2888 return 1 if $type eq "VoidCallback";
2889 return 1 if $type eq "IDBKey";
2895 my $signature = shift;
2898 my $type = GetTypeFromSignature($signature);
2900 return "$value" if $type eq "JSObject";
2901 return "$value->BooleanValue()" if $type eq "boolean";
2902 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
2904 return "toInt32($value)" if $type eq "long";
2905 return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsigned short";
2906 return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
2907 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
2908 return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
2909 return "toWebCoreDate($value)" if $type eq "Date";
2911 if ($type eq "DOMString" or $type eq "DOMUserData") {
2915 die "Unexpected SerializedScriptValue" if $type eq "SerializedScriptValue";
2917 if ($type eq "IDBKey") {
2918 $implIncludes{"IDBBindingUtilities.h"} = 1;
2919 $implIncludes{"IDBKey.h"} = 1;
2920 return "createIDBKeyFromValue($value)";
2923 if ($type eq "DOMObject") {
2924 $implIncludes{"ScriptValue.h"} = 1;
2925 return "ScriptValue($value)";
2928 if ($type eq "NodeFilter") {
2929 return "V8DOMWrapper::wrapNativeNodeFilter($value)";
2932 if ($type eq "SVGRect") {
2933 $implIncludes{"FloatRect.h"} = 1;
2936 # Default, assume autogenerated type conversion routines
2937 if ($type eq "EventTarget") {
2938 $implIncludes{"V8Node.h"} = 1;
2940 # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
2941 return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2944 if ($type eq "XPathNSResolver") {
2945 return "V8DOMWrapper::getXPathNSResolver($value)";
2948 AddIncludesForType($type);
2950 if (IsDOMNodeType($type)) {
2951 $implIncludes{"V8${type}.h"} = 1;
2953 # Perform type checks on the parameter, if it is expected Node type,
2955 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2957 $implIncludes{"V8$type.h"} = 1;
2959 # Perform type checks on the parameter, if it is expected Node type,
2961 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2968 return "V8Event.h" if $type eq "DOMTimeStamp";
2969 return "EventListener.h" if $type eq "EventListener";
2970 return "EventTarget.h" if $type eq "EventTarget";
2971 return "SerializedScriptValue.h" if $type eq "SerializedScriptValue";
2972 return "ScriptValue.h" if $type eq "DOMObject";
2973 return "V8${type}.h";
2976 sub CreateCustomSignature
2978 my $function = shift;
2979 my $count = @{$function->parameters};
2980 my $name = $function->signature->name;
2981 my $result = " const int ${name}Argc = ${count};\n" .
2982 " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { ";
2984 foreach my $parameter (@{$function->parameters}) {
2985 if ($first) { $first = 0; }
2986 else { $result .= ", "; }
2987 if (IsWrapperType($parameter->type)) {
2988 if ($parameter->type eq "XPathNSResolver") {
2989 # Special case for XPathNSResolver. All other browsers accepts a callable,
2990 # so, even though it's against IDL, accept objects here.
2991 $result .= "v8::Handle<v8::FunctionTemplate>()";
2993 my $type = $parameter->type;
2994 my $header = GetV8HeaderName($type);
2995 $implIncludes{$header} = 1;
2996 $result .= "V8${type}::GetRawTemplate()";
2999 $result .= "v8::Handle<v8::FunctionTemplate>()";
3003 $result .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n";
3008 sub RequiresCustomSignature
3010 my $function = shift;
3011 # No signature needed for Custom function
3012 if ($function->signature->extendedAttributes->{"Custom"} ||
3013 $function->signature->extendedAttributes->{"V8Custom"}) {
3016 # No signature needed for overloaded function
3017 if (@{$function->{overloads}} > 1) {
3020 # Type checking is performed in the generated code
3021 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
3024 foreach my $parameter (@{$function->parameters}) {
3025 if ($parameter->extendedAttributes->{"Optional"} || $parameter->extendedAttributes->{"Callback"}) {
3030 foreach my $parameter (@{$function->parameters}) {
3031 if (IsWrapperType($parameter->type)) {
3039 # FIXME: Sort this array.
3040 my %non_wrapper_types = (
3044 'unsigned int' => 1,
3046 'unsigned short' => 1,
3048 'unsigned long' => 1,
3051 'unsigned long long' => 1,
3054 'SerializedScriptValue' => 1,
3055 'SVGPaintType' => 1,
3056 'DOMTimeStamp' => 1,
3061 'EventListener' => 1,
3069 my $type = $codeGenerator->StripModule(shift);
3070 return !($non_wrapper_types{$type});
3077 return 1 if $type eq 'Attr';
3078 return 1 if $type eq 'CDATASection';
3079 return 1 if $type eq 'Comment';
3080 return 1 if $type eq 'Document';
3081 return 1 if $type eq 'DocumentFragment';
3082 return 1 if $type eq 'DocumentType';
3083 return 1 if $type eq 'Element';
3084 return 1 if $type eq 'EntityReference';
3085 return 1 if $type eq 'HTMLCanvasElement';
3086 return 1 if $type eq 'HTMLDocument';
3087 return 1 if $type eq 'HTMLElement';
3088 return 1 if $type eq 'HTMLFormElement';
3089 return 1 if $type eq 'HTMLTableCaptionElement';
3090 return 1 if $type eq 'HTMLTableSectionElement';
3091 return 1 if $type eq 'Node';
3092 return 1 if $type eq 'ProcessingInstruction';
3093 return 1 if $type eq 'SVGElement';
3094 return 1 if $type eq 'SVGDocument';
3095 return 1 if $type eq 'SVGSVGElement';
3096 return 1 if $type eq 'SVGUseElement';
3097 return 1 if $type eq 'Text';
3103 sub ReturnNativeToJSValue
3105 my $signature = shift;
3108 my $type = GetTypeFromSignature($signature);
3110 return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
3111 return "return v8Boolean($value)" if $type eq "boolean";
3112 return "return v8::Handle<v8::Value>()" if $type eq "void"; # equivalent to v8::Undefined()
3114 # For all the types where we use 'int' as the representation type,
3115 # we use Integer::New which has a fast Smi conversion check.
3116 my $nativeType = GetNativeType($type);
3117 return "return v8::Integer::New($value)" if $nativeType eq "int";
3118 return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
3120 return "return v8DateOrNull($value)" if $type eq "Date";
3121 # long long and unsigned long long are not representable in ECMAScript.
3122 return "return v8::Number::New(static_cast<double>($value))" if $type eq "long long" or $type eq "unsigned long long";
3123 return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
3124 return "return $value.v8Value()" if $nativeType eq "ScriptValue";
3126 if ($codeGenerator->IsStringType($type)) {
3127 my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
3128 if (defined $conv) {
3129 return "return v8StringOrNull($value)" if $conv eq "Null";
3130 return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
3131 return "return v8StringOrFalse($value)" if $conv eq "False";
3133 die "Unknown value for ConvertNullStringTo extended attribute";
3135 $conv = $signature->extendedAttributes->{"ConvertScriptString"};
3136 return "return v8StringOrNull($value)" if $conv;
3137 return "return v8String($value)";
3140 AddIncludesForType($type);
3142 # special case for non-DOM node interfaces
3143 if (IsDOMNodeType($type)) {
3144 return "return toV8(${value}" . ($signature->extendedAttributes->{"ReturnsNew"} ? ", true)" : ")");
3147 if ($type eq "EventTarget") {
3148 return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
3151 if ($type eq "EventListener") {
3152 $implIncludes{"V8AbstractEventListener.h"} = 1;
3153 return "return ${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(v8::Null())";
3156 if ($type eq "SerializedScriptValue") {
3157 $implIncludes{"$type.h"} = 1;
3158 return "return $value->deserialize()";
3161 $implIncludes{"wtf/RefCounted.h"} = 1;
3162 $implIncludes{"wtf/RefPtr.h"} = 1;
3163 $implIncludes{"wtf/GetPtr.h"} = 1;
3165 return "return toV8($value)";
3171 if (defined($IMPL)) {
3172 # Write content to file.
3173 print $IMPL @implContentHeader;
3175 print $IMPL @implFixedHeader;
3177 foreach my $implInclude (sort keys(%implIncludes)) {
3178 my $checkType = $implInclude;
3179 $checkType =~ s/\.h//;
3181 if ($implInclude =~ /wtf/) {
3182 print $IMPL "#include \<$implInclude\>\n";
3184 print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
3189 print $IMPL @implContentDecls;
3190 print $IMPL @implContent;
3195 @implFixedHeader = ();
3196 @implHeaderContent = ();
3197 @implContentDecls = ();
3201 if (defined($HEADER)) {
3202 # Write content to file.
3203 print $HEADER @headerContent;
3207 @headerContent = ();
3211 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
3212 sub IsSVGTypeNeedingContextParameter
3214 my $implClassName = shift;
3216 return 0 unless $implClassName =~ /SVG/;
3217 return 0 if $implClassName =~ /Element/;
3218 return 0 if $codeGenerator->IsSVGAnimatedType($implClassName);
3219 return 0 if $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
3221 my @noContextNeeded = ("SVGColor", "SVGDocument", "SVGPaintType", "SVGPaint", "SVGZoomEvent");
3222 foreach (@noContextNeeded) {
3223 return 0 if $implClassName eq $_;
3228 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
3229 sub GenerateSVGContextAssignment
3231 my $srcType = shift;
3235 $result = GenerateSVGContextRetrieval($srcType, $indent);
3236 $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
3241 # FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
3242 sub GenerateSVGContextRetrieval
3244 my $srcType = shift;
3247 my $contextDecl = "imp";
3248 if (IsSVGTypeNeedingContextParameter($srcType)) {
3249 $contextDecl = "V8Proxy::svgContext($contextDecl)";
3252 return $indent . "SVGElement* context = $contextDecl;\n";
3255 sub IsSVGListMutator
3257 my $functionName = shift;
3259 return 1 if $functionName eq "clear";
3260 return 1 if $functionName eq "initialize";
3261 return 1 if $functionName eq "insertItemBefore";
3262 return 1 if $functionName eq "replaceItem";
3263 return 1 if $functionName eq "removeItem";
3264 return 1 if $functionName eq "appendItem";
3269 sub GetVisibleInterfaceName
3271 my $interfaceName = shift;
3273 return "DOMException" if $interfaceName eq "DOMCoreException";
3274 return "FormData" if $interfaceName eq "DOMFormData";
3275 return $interfaceName;
3278 sub GetCallbackClassName
3280 my $interfaceName = shift;
3282 return "V8CustomVoidCallback" if $interfaceName eq "VoidCallback";
3283 return "V8$interfaceName";
3286 sub ConvertToV8Parameter
3288 my $signature = shift;
3289 my $nativeType = shift;
3290 my $variableName = shift;
3294 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8Parameter/;
3295 if ($signature->type eq "DOMString") {
3296 $implIncludes{"V8BindingMacros.h"} = 1;
3297 my $macro = "STRING_TO_V8PARAMETER_EXCEPTION_BLOCK";
3298 $macro .= "_$suffix" if $suffix;
3299 return "$macro($nativeType, $variableName, $value);"
3301 # Don't know how to properly check for conversion exceptions when $parameter->type is "DOMUserData"
3302 return "$nativeType $variableName($value, true);";
3306 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
3307 sub GetRuntimeEnableFunctionName
3309 my $signature = shift;
3311 # If a parameter is given (e.g. "EnabledAtRuntime=FeatureName") return the RuntimeEnabledFeatures::{FeatureName}Enabled() method.
3312 return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->extendedAttributes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"EnabledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "1");
3314 # Otherwise return a function named RuntimeEnabledFeatures::{methodName}Enabled().
3315 return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->name) . "Enabled";