2 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006 Apple Computer, Inc.
7 # Copyright (C) 2007, 2008, 2009 Google Inc.
8 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
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 = ();
45 my $headerTemplate = << "EOF";
47 This file is part of the WebKit open source project.
48 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
50 This library is free software; you can redistribute it and/or
51 modify it under the terms of the GNU Library General Public
52 License as published by the Free Software Foundation; either
53 version 2 of the License, or (at your option) any later version.
55 This library is distributed in the hope that it will be useful,
56 but WITHOUT ANY WARRANTY; without even the implied warranty of
57 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
58 Library General Public License for more details.
60 You should have received a copy of the GNU Library General Public License
61 along with this library; see the file COPYING.LIB. If not, write to
62 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
63 Boston, MA 02111-1307, USA.
73 $codeGenerator = shift;
75 $outputHeadersDir = shift;
77 bless($reference, $object);
89 # Workaround for V8 bindings difference where RGBColor is not a POD type.
93 return $codeGenerator->IsPodType($type);
96 # Params: 'domClass' struct
100 my $dataNode = shift;
103 # Start actual generation
104 if ($dataNode->extendedAttributes->{"Callback"}) {
105 $object->GenerateCallbackHeader($dataNode);
106 $object->GenerateCallbackImplementation($dataNode);
108 $object->GenerateHeader($dataNode);
109 $object->GenerateImplementation($dataNode);
112 my $name = $dataNode->name;
114 # Open files for writing
115 my $headerFileName = "$outputHeadersDir/V8$name.h";
116 my $implFileName = "$outputDir/V8$name.cpp";
118 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
119 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
122 # Params: 'idlDocument' struct
126 my $dataNode = shift;
128 $module = $dataNode->module;
131 sub AvoidInclusionOfType
135 # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
136 return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
140 sub AddIncludesForType
142 my $type = $codeGenerator->StripModule(shift);
144 # When we're finished with the one-file-per-class
145 # reorganization, we won't need these special cases.
146 if (!$codeGenerator->IsPrimitiveType($type) and !AvoidInclusionOfType($type) and $type ne "Date") {
147 # default, include the same named file
148 $implIncludes{GetV8HeaderName(${type})} = 1;
150 if ($type =~ /SVGPathSeg/) {
152 $joinedName =~ s/Abs|Rel//;
153 $implIncludes{"${joinedName}.h"} = 1;
157 # additional includes (things needed to compile the bindings but not the header)
159 if ($type eq "CanvasRenderingContext2D") {
160 $implIncludes{"CanvasGradient.h"} = 1;
161 $implIncludes{"CanvasPattern.h"} = 1;
162 $implIncludes{"CanvasStyle.h"} = 1;
165 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
166 $implIncludes{"PlatformString.h"} = 1;
169 if ($type eq "CSSStyleDeclaration") {
170 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
173 if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
174 # So we can get String -> AtomicString conversion for namedItem().
175 $implIncludes{"wtf/text/AtomicString.h"} = 1;
179 sub AddIncludesForSVGAnimatedType
182 $type =~ s/SVGAnimated//;
184 if ($type eq "Point" or $type eq "Rect") {
185 $implIncludes{"Float$type.h"} = 1;
186 } elsif ($type eq "String") {
187 $implIncludes{"PlatformString.h"} = 1;
190 $implIncludes{"SVGAnimatedTemplate.h"} = 1;
193 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
194 sub GenerateConditionalString
197 my $conditional = $node->extendedAttributes->{"Conditional"};
199 if ($conditional =~ /&/) {
200 return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
201 } elsif ($conditional =~ /\|/) {
202 return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
204 return "ENABLE(" . $conditional . ")";
214 my $dataNode = shift;
216 my $interfaceName = $dataNode->name;
217 my $className = "V8$interfaceName";
218 my $implClassName = $interfaceName;
220 # Copy contents of parent classes except the first parent or if it is
222 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
224 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
226 # - Add default header template
227 push(@headerContent, GenerateHeaderContentHeader($dataNode));
229 # Get correct pass/store types respecting PODType flag
230 my $podType = $dataNode->extendedAttributes->{"PODType"};
232 my %headerInclues = ();
233 $headerIncludes{"$podType.h"} = 1 if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
234 $headerIncludes{"wtf/text/StringHash.h"} = 1;
235 $headerIncludes{"WrapperTypeInfo.h"} = 1;
236 my $headerClassInclude = GetHeaderClassInclude($implClassName);
237 $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
239 foreach my $headerInclude (sort keys(%headerIncludes)) {
240 push(@headerContent, "#include \"${headerInclude}\"\n");
243 push(@headerContent, "#include <v8.h>\n");
244 push(@headerContent, "#include <wtf/HashMap.h>\n");
246 push(@headerContent, "\nnamespace WebCore {\n");
248 push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n");
250 push(@headerContent, "\nclass $className {\n");
252 my $nativeType = GetNativeTypeForConversions($interfaceName);
254 $nativeType = "V8SVGPODTypeWrapper<${nativeType} >";
256 my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
257 push(@headerContent, <<END);
260 static bool HasInstance(v8::Handle<v8::Value> value);
261 static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
262 static v8::Persistent<v8::FunctionTemplate> GetTemplate();
263 static ${nativeType}* toNative(v8::Handle<v8::Object>);
264 static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
265 static void derefObject(void*);
266 static WrapperTypeInfo info;
268 if (IsActiveDomType($implClassName)) {
269 push(@headerContent, " static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
272 if ($implClassName eq "DOMWindow") {
273 push(@headerContent, <<END);
274 static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
278 if ($implClassName eq "HTMLDocument") {
279 push(@headerContent, <<END);
280 static v8::Local<v8::Object> WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl);
281 static v8::Handle<v8::Value> GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key);
285 my @enabledAtRuntime;
286 foreach my $function (@{$dataNode->functions}) {
287 my $name = $function->signature->name;
288 my $attrExt = $function->signature->extendedAttributes;
290 if ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
291 push(@headerContent, <<END);
292 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
296 if ($attrExt->{"EnabledAtRuntime"}) {
297 push(@enabledAtRuntime, $function);
301 if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
302 push(@headerContent, <<END);
303 static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args);
307 foreach my $attribute (@{$dataNode->attributes}) {
308 my $name = $attribute->signature->name;
309 my $attrExt = $attribute->signature->extendedAttributes;
310 if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"}
311 || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
312 push(@headerContent, <<END);
313 static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);
316 if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"}
317 || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) {
318 push(@headerContent, <<END);
319 static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
322 if ($attrExt->{"EnabledAtRuntime"}) {
323 push(@enabledAtRuntime, $attribute);
327 GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
328 GenerateHeaderCustomCall($dataNode);
329 GenerateHeaderCustomInternalFieldIndices($dataNode);
331 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
332 push(@headerContent, <<END);
333 static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
334 static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
338 push(@headerContent, <<END);
341 v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
343 if (IsRefPtrType($implClassName)) {
344 push(@headerContent, <<END);
345 v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} >${forceNewObjectParameter});
349 push(@headerContent, "}\n\n");
350 push(@headerContent, "#endif // $className" . "_h\n");
352 my $conditionalString = GenerateConditionalString($dataNode);
353 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
356 sub GetInternalFields
358 my $dataNode = shift;
359 my $name = $dataNode->name;
361 my @customInternalFields = ();
363 # We can't ask whether a parent type has a given extendedAttribute, so special-case Node, AbstractWorker and WorkerContext to include all sub-types.
364 # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't.
365 if ($dataNode->extendedAttributes->{"EventTarget"} || IsNodeSubType($dataNode) || IsSubType($dataNode, "AbstractWorker") || IsSubType($dataNode, "WorkerContext")
366 || $name eq "SVGElementInstance") {
367 push(@customInternalFields, "eventListenerCacheIndex");
370 if (IsSubType($dataNode, "Document")) {
371 push(@customInternalFields, "implementationIndex");
372 } elsif ($name eq "DOMWindow") {
373 push(@customInternalFields, "enteredIsolatedWorldIndex");
375 return @customInternalFields;
378 sub GetHeaderClassInclude
380 my $className = shift;
381 if ($className =~ /SVGPathSeg/) {
382 $className =~ s/Abs|Rel//;
384 return "" if (AvoidInclusionOfType($className));
385 return "SVGAnimatedTemplate.h" if ($codeGenerator->IsSVGAnimatedType($className));
386 return "${className}.h";
389 sub GenerateHeaderCustomInternalFieldIndices
391 my $dataNode = shift;
392 my @customInternalFields = GetInternalFields($dataNode);
393 my $customFieldCounter = 0;
394 foreach my $customInternalField (@customInternalFields) {
395 push(@headerContent, <<END);
396 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
398 $customFieldCounter++;
400 push(@headerContent, <<END);
401 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
405 my %indexerSpecialCases = (
407 "HTMLAppletElement" => 1,
408 "HTMLEmbedElement" => 1,
409 "HTMLObjectElement" => 1
412 sub GenerateHeaderNamedAndIndexedPropertyAccessors
414 my $dataNode = shift;
415 my $interfaceName = $dataNode->name;
416 my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
417 my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
418 my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
419 my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
420 my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
421 my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
422 if ($interfaceName eq "HTMLOptionsCollection") {
423 $interfaceName = "HTMLCollection";
424 $hasCustomIndexedGetter = 1;
425 $hasCustomNamedGetter = 1;
427 if ($interfaceName eq "DOMWindow") {
428 $hasCustomDeleterr = 0;
431 if ($interfaceName eq "HTMLSelectElement" || $interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
432 $hasCustomNamedGetter = 1;
434 if ($interfaceName eq "HTMLDocument") {
435 $hasCustomNamedGetter = 0;
436 $hasCustomIndexedGetter = 0;
438 my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
440 if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
441 push(@headerContent, <<END);
442 static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
446 if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
447 push(@headerContent, <<END);
448 static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
451 if ($hasCustomDeleters) {
452 push(@headerContent, <<END);
453 static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
456 if ($hasCustomNamedGetter) {
457 push(@headerContent, <<END);
458 static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
461 if ($hasCustomNamedSetter) {
462 push(@headerContent, <<END);
463 static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
466 if ($hasCustomDeleters) {
467 push(@headerContent, <<END);
468 static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
471 if ($hasCustomEnumerator) {
472 push(@headerContent, <<END);
473 static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
474 static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
479 sub GenerateHeaderCustomCall
481 my $dataNode = shift;
483 if ($dataNode->extendedAttributes->{"CustomCall"}) {
484 push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
486 if ($dataNode->name eq "Event") {
487 push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
488 push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n");
490 if ($dataNode->name eq "Location") {
491 push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
492 push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
493 push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n");
497 sub GenerateSetDOMException
502 $result .= $indent . "if (UNLIKELY(ec)) {\n";
503 $result .= $indent . " V8Proxy::setDOMException(ec);\n";
504 $result .= $indent . " return v8::Handle<v8::Value>();\n";
505 $result .= $indent . "}\n";
512 my $dataNode = shift;
513 my $parentType = shift;
514 return 1 if ($dataNode->name eq $parentType);
515 foreach (@allParents) {
516 my $parent = $codeGenerator->StripModule($_);
517 return 1 if $parent eq $parentType;
524 my $dataNode = shift;
525 return IsSubType($dataNode, "Node");
528 sub GenerateDomainSafeFunctionGetter
530 my $function = shift;
531 my $implClassName = shift;
533 my $className = "V8" . $implClassName;
534 my $funcName = $function->signature->name;
536 my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
537 if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
538 $signature = "v8::Local<v8::Signature>()";
541 my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature);
543 push(@implContentDecls, <<END);
544 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
546 INC_STATS(\"DOM.$implClassName.$funcName._get\");
547 static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
548 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
549 if (holder.IsEmpty()) {
550 // can only reach here by 'object.__proto__.func', and it should passed
551 // domain security check already
552 return privateTemplate->GetFunction();
554 ${implClassName}* imp = ${className}::toNative(holder);
555 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
556 static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
557 return sharedTemplate->GetFunction();
559 return privateTemplate->GetFunction();
565 sub GenerateConstructorGetter
567 my $implClassName = shift;
569 push(@implContentDecls, <<END);
570 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
572 INC_STATS(\"DOM.$implClassName.constructors._get\");
573 v8::Handle<v8::Value> data = info.Data();
574 ASSERT(data->IsExternal() || data->IsNumber());
575 WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data);
578 if ($implClassName eq "DOMWindow") {
579 push(@implContentDecls, <<END);
580 // Get the proxy corresponding to the DOMWindow if possible to
581 // make sure that the constructor function is constructed in the
582 // context of the DOMWindow and not in the context of the caller.
583 return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder()));
585 } elsif ($implClassName eq "DedicatedWorkerContext" or $implClassName eq "WorkerContext" or $implClassName eq "SharedWorkerContext") {
586 push(@implContentDecls, <<END);
587 return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder()));
590 push(@implContentDecls, " return v8::Handle<v8::Value>();");
593 push(@implContentDecls, <<END);
599 sub GenerateNormalAttrGetter
601 my $attribute = shift;
602 my $dataNode = shift;
603 my $implClassName = shift;
604 my $interfaceName = shift;
606 my $attrExt = $attribute->signature->extendedAttributes;
608 my $attrName = $attribute->signature->name;
610 my $attrType = GetTypeFromSignature($attribute->signature);
611 my $attrIsPodType = IsPodType($attrType);
613 my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
614 my $isPodType = IsPodType($implClassName);
618 $implClassName = GetNativeType($implClassName);
619 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
622 # Special case: SVGZoomEvent's attributes are all read-only
623 if ($implClassName eq "SVGZoomEvent") {
628 # Special case: SVGSVGEelement::viewport is read-only
629 if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) {
634 # Special case for SVGColor
635 if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) {
639 my $getterStringUsesImp = $implClassName ne "float";
642 my $conditionalString = GenerateConditionalString($attribute->signature);
643 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
645 push(@implContentDecls, <<END);
646 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
648 INC_STATS(\"DOM.$implClassName.$attrName._get\");
652 push(@implContentDecls, <<END);
653 V8SVGPODTypeWrapper<$implClassName>* impWrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());
654 $implClassName impInstance = *impWrapper;
656 if ($getterStringUsesImp) {
657 push(@implContentDecls, <<END);
658 $implClassName* imp = &impInstance;
662 } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
663 if ($interfaceName eq "DOMWindow") {
664 push(@implContentDecls, <<END);
665 v8::Handle<v8::Object> holder = info.Holder();
668 # perform lookup first
669 push(@implContentDecls, <<END);
670 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
671 if (holder.IsEmpty())
672 return v8::Handle<v8::Value>();
675 push(@implContentDecls, <<END);
676 ${implClassName}* imp = V8${implClassName}::toNative(holder);
679 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
680 my $url = $attribute->signature->extendedAttributes->{"URL"};
681 if ($getterStringUsesImp && $reflect && !$url && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
682 # Generate super-compact call for regular attribute getter:
683 my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect;
684 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
685 $implIncludes{"${namespace}.h"} = 1;
686 push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
687 push(@implContentDecls, "}\n\n");
688 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
690 # Skip the rest of the function!
692 push(@implContentDecls, <<END);
693 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
697 # Generate security checks if necessary
698 if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
699 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName()))\n return v8::Handle<v8::Value>();\n\n");
700 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
701 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument()))\n return v8::Handle<v8::Value>();\n\n");
704 my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
705 if ($useExceptions) {
706 $implIncludes{"ExceptionCode.h"} = 1;
707 push(@implContentDecls, " ExceptionCode ec = 0;\n");
710 if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
711 $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
714 my $returnType = GetTypeFromSignature($attribute->signature);
717 if ($getterStringUsesImp) {
718 $getterString = "imp->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
719 $getterString .= "ec" if $useExceptions;
720 $getterString .= ")";
722 $getterString = "impInstance";
728 if ($attrIsPodType) {
729 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
731 my $getter = $getterString;
732 $getter =~ s/imp->//;
734 my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
736 my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
737 if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
738 if (IsPodType($implClassName)) {
739 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, impWrapper)";
740 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
742 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
743 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
746 if ($implClassIsAnimatedType) {
747 # We can't hash member function pointers, so instead generate
748 # some hashing material based on the names of the methods.
749 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
750 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
751 push(@implContentDecls, " RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
753 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
754 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
759 if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
760 push(@implContentDecls, " if (!imp->document())\n");
761 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
764 if ($useExceptions) {
765 if ($nativeType =~ /^V8Parameter/) {
766 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $getterString) . ";\n");
768 push(@implContentDecls, " $nativeType v = $getterString;\n");
770 push(@implContentDecls, GenerateSetDOMException(" "));
772 $result .= ".release()" if (IsRefPtrType($returnType));
774 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
775 $result = $getterString;
778 # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
779 # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
780 # the newly created wrapper into an internal field of the holder object.
781 if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"})
782 && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow"
783 && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) {
784 AddIncludesForType($returnType);
785 my $domMapFunction = GetDomMapFunction(0, $returnType);
786 # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
787 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
788 push(@implContentDecls, " RefPtr<$returnType> result = ${getterString};\n");
789 push(@implContentDecls, " v8::Handle<v8::Value> wrapper = result.get() ? ${domMapFunction}.get(result.get()) : v8::Handle<v8::Value>();\n");
790 push(@implContentDecls, " if (wrapper.IsEmpty()) {\n");
791 push(@implContentDecls, " wrapper = toV8(result.get());\n");
792 push(@implContentDecls, " if (!wrapper.IsEmpty())\n");
793 if ($dataNode->name eq "DOMWindow") {
794 push(@implContentDecls, " V8DOMWrapper::setHiddenWindowReference(imp->frame(), wrapper);\n");
796 push(@implContentDecls, " V8DOMWrapper::setHiddenReference(info.Holder(), wrapper);\n");
798 push(@implContentDecls, " }\n");
799 push(@implContentDecls, " return wrapper;\n");
800 push(@implContentDecls, "}\n\n");
801 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
806 if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
807 if ($attrIsPodType) {
808 push(@implContentDecls, GenerateSVGContextAssignment($implClassName, "wrapper.get()", " "));
810 push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, " "));
811 # The templating associated with passing withSVGContext()'s return value directly into toV8 can get compilers confused,
812 # so just manually set the return value to a PassRefPtr of the expected type.
813 push(@implContentDecls, " PassRefPtr<$attrType> resultAsPassRefPtr = V8Proxy::withSVGContext($result, context);\n");
814 $result = "resultAsPassRefPtr";
818 if ($attrIsPodType) {
819 $implIncludes{"V8${attrType}.h"} = 1;
820 push(@implContentDecls, " return toV8(wrapper.release().get());\n");
822 push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n");
825 push(@implContentDecls, "}\n\n"); # end of getter
826 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
829 sub GenerateNormalAttrSetter
831 my $attribute = shift;
832 my $dataNode = shift;
833 my $implClassName = shift;
834 my $interfaceName = shift;
836 $implIncludes{"V8BindingMacros.h"} = 1;
838 my $attrExt = $attribute->signature->extendedAttributes;
840 my $conditionalString = GenerateConditionalString($attribute->signature);
841 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
843 push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
844 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
846 my $isPodType = IsPodType($implClassName);
849 $implClassName = GetNativeType($implClassName);
850 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
851 push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n");
852 push(@implContentDecls, " $implClassName impInstance = *wrapper;\n");
853 push(@implContentDecls, " $implClassName* imp = &impInstance;\n");
855 } elsif ($attrExt->{"v8OnProto"}) {
856 if ($interfaceName eq "DOMWindow") {
857 push(@implContentDecls, <<END);
858 v8::Handle<v8::Object> holder = info.Holder();
861 # perform lookup first
862 push(@implContentDecls, <<END);
863 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
864 if (holder.IsEmpty())
868 push(@implContentDecls, <<END);
869 ${implClassName}* imp = V8${implClassName}::toNative(holder);
872 my $attrType = GetTypeFromSignature($attribute->signature);
873 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
874 if ($reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
875 # Generate super-compact call for regular attribute setter:
876 my $contentAttributeName = $reflect eq "1" ? lc $attrName : $reflect;
877 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
878 $implIncludes{"${namespace}.h"} = 1;
879 push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
880 push(@implContentDecls, "}\n\n");
881 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
883 # Skip the rest of the function!
886 push(@implContentDecls, <<END);
887 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
891 my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
892 if ($attribute->signature->type eq "EventListener") {
893 if ($dataNode->name eq "DOMWindow") {
894 push(@implContentDecls, " if (!imp->document())\n");
895 push(@implContentDecls, " return;\n");
898 my $value = JSValueToNative($attribute->signature, "value");
899 if ($nativeType =~ /^V8Parameter/) {
900 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
902 push(@implContentDecls, " $nativeType v = $value;\n");
907 my $returnType = GetTypeFromSignature($attribute->signature);
908 if (IsRefPtrType($returnType)) {
909 $result = "WTF::getPtr(" . $result . ")";
912 my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
914 if ($useExceptions) {
915 $implIncludes{"ExceptionCode.h"} = 1;
916 push(@implContentDecls, " ExceptionCode ec = 0;\n");
919 if ($implClassName eq "float") {
920 push(@implContentDecls, " *imp = $result;\n");
922 if ($attribute->signature->type eq "EventListener") {
923 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
924 $implIncludes{"V8AbstractEventListener.h"} = 1;
925 push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n");
926 if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
927 $implIncludes{"V8EventListenerList.h"} = 1;
928 $implIncludes{"V8WorkerContextErrorHandler.h"} = 1;
929 push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
931 push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)");
934 my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
935 push(@implContentDecls, " imp->$setterExpressionPrefix$result");
937 push(@implContentDecls, ", ec") if $useExceptions;
938 push(@implContentDecls, ");\n");
941 if ($useExceptions) {
942 push(@implContentDecls, " if (UNLIKELY(ec))\n");
943 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
947 push(@implContentDecls, " wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
948 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
949 $implIncludes{"SVGElement.h"} = 1;
951 my $currentObject = "imp";
953 $currentObject = "wrapper";
956 push(@implContentDecls, " if (SVGElement* context = V8Proxy::svgContext($currentObject))\n");
957 push(@implContentDecls, " context->svgAttributeChanged(imp->associatedAttributeName());\n");
960 push(@implContentDecls, " return;\n");
961 push(@implContentDecls, "}\n\n"); # end of setter
962 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
965 sub GetFunctionTemplateCallbackName
968 $interfaceName = shift;
970 my $name = $function->signature->name;
972 if ($function->signature->extendedAttributes->{"Custom"} ||
973 $function->signature->extendedAttributes->{"V8Custom"}) {
974 if ($function->signature->extendedAttributes->{"Custom"} &&
975 $function->signature->extendedAttributes->{"V8Custom"}) {
976 die "Custom and V8Custom should be mutually exclusive!"
978 return "V8${interfaceName}::${name}Callback";
980 return "${interfaceName}Internal::${name}Callback";
984 sub GenerateNewFunctionTemplate
987 $interfaceName = shift;
990 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
991 return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
994 sub GenerateEventListenerCallback
996 my $implClassName = shift;
997 my $functionName = shift;
998 my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
999 my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1000 my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1002 push(@implContentDecls, <<END);
1003 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1005 INC_STATS("DOM.${implClassName}.${functionName}EventListener()");
1006 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType});
1008 V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue());
1009 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex);
1011 return v8::Undefined();
1017 sub GenerateParametersCheckExpression
1019 my $numParameters = shift;
1020 my $function = shift;
1022 my @andExpression = ();
1023 push(@andExpression, "args.Length() == $numParameters");
1024 my $parameterIndex = 0;
1025 foreach $parameter (@{$function->parameters}) {
1026 last if $parameterIndex >= $numParameters;
1027 my $value = "args[$parameterIndex]";
1028 my $type = GetTypeFromSignature($parameter);
1030 # Only DOMString or wrapper types are checked.
1031 # For DOMString, Null, Undefined and any Object are accepted too, as
1032 # these are acceptable values for a DOMString argument (any Object can
1033 # be converted to a string via .toString).
1034 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())") if $codeGenerator->IsStringType($type);
1035 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))") if IsWrapperType($type);
1039 my $res = join(" && ", @andExpression);
1040 $res = "($res)" if @andExpression > 1;
1044 sub GenerateFunctionParametersCheck
1046 my $function = shift;
1048 my @orExpression = ();
1049 my $numParameters = 0;
1050 foreach $parameter (@{$function->parameters}) {
1051 if ($parameter->extendedAttributes->{"Optional"}) {
1052 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1056 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1057 return join(" || ", @orExpression);
1060 sub GenerateOverloadedFunctionCallback
1062 my $function = shift;
1063 my $dataNode = shift;
1064 my $implClassName = shift;
1066 # Generate code for choosing the correct overload to call. Overloads are
1067 # chosen based on the total number of arguments passed and the type of
1068 # values passed in non-primitive argument slots. When more than a single
1069 # overload is applicable, precedence is given according to the order of
1070 # declaration in the IDL.
1072 my $name = $function->signature->name;
1073 push(@implContentDecls, <<END);
1074 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1076 INC_STATS(\"DOM.$implClassName.$name\");
1079 foreach my $overload (@{$function->{overloads}}) {
1080 my $parametersCheck = GenerateFunctionParametersCheck($overload);
1081 push(@implContentDecls, " if ($parametersCheck)\n");
1082 push(@implContentDecls, " return ${name}$overload->{overloadIndex}Callback(args);\n");
1084 push(@implContentDecls, <<END);
1085 V8Proxy::throwTypeError();
1086 return notHandledByInterceptor();
1088 push(@implContentDecls, "}\n\n");
1091 sub GenerateFunctionCallback
1093 my $function = shift;
1094 my $dataNode = shift;
1095 my $implClassName = shift;
1097 my $interfaceName = $dataNode->name;
1098 my $name = $function->signature->name;
1100 if (@{$function->{overloads}} > 1) {
1101 # Append a number to an overloaded method's name to make it unique:
1102 $name = $name . $function->{overloadIndex};
1105 # Adding and removing event listeners are not standard callback behavior,
1106 # but they are extremely consistent across the various classes that take event listeners,
1107 # so we can generate them as a "special case".
1108 if ($name eq "addEventListener") {
1109 GenerateEventListenerCallback($implClassName, "add");
1111 } elsif ($name eq "removeEventListener") {
1112 GenerateEventListenerCallback($implClassName, "remove");
1116 push(@implContentDecls, <<END);
1117 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1119 INC_STATS(\"DOM.$implClassName.$name\");
1122 my $numParameters = @{$function->parameters};
1124 my $requiresAllArguments = $function->signature->extendedAttributes->{"RequiresAllArguments"};
1125 if ($requiresAllArguments) {
1126 my $numMandatoryParams = @{$function->parameters};
1127 foreach my $param (reverse(@{$function->parameters})) {
1128 if ($param->extendedAttributes->{"Optional"}) {
1129 $numMandatoryParams--;
1134 push(@implContentDecls, " if (args.Length() < $numMandatoryParams)\n");
1135 if ($requiresAllArguments eq "Raise") {
1136 push(@implContentDecls, " return throwError(\"Not enough arguments\", V8Proxy::SyntaxError);\n");
1138 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1142 if (IsPodType($implClassName)) {
1143 my $nativeClassName = GetNativeType($implClassName);
1144 push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* impWrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n");
1145 push(@implContentDecls, " $nativeClassName impInstance = *impWrapper;\n");
1146 push(@implContentDecls, " $nativeClassName* imp = &impInstance;\n");
1148 push(@implContentDecls, <<END);
1149 ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
1153 # Check domain security if needed
1154 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
1155 || $interfaceName eq "DOMWindow")
1156 && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1157 # We have not find real use cases yet.
1158 push(@implContentDecls, <<END);
1159 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
1160 return v8::Handle<v8::Value>();
1164 my $raisesExceptions = @{$function->raisesExceptions};
1165 if (!$raisesExceptions) {
1166 foreach my $parameter (@{$function->parameters}) {
1167 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1168 $raisesExceptions = 1;
1173 if ($raisesExceptions) {
1174 $implIncludes{"ExceptionCode.h"} = 1;
1175 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1176 push(@implContentDecls, " {\n");
1177 # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1178 # of objects (like Strings) declared later, causing compile errors. The block scope ends
1179 # right before the label 'fail:'.
1182 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1183 push(@implContentDecls, <<END);
1184 OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));
1186 return v8::Undefined();
1188 $implIncludes{"ScriptCallStack.h"} = 1;
1190 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
1191 push(@implContentDecls, <<END);
1192 if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))
1193 return v8::Handle<v8::Value>();
1198 foreach my $parameter (@{$function->parameters}) {
1199 TranslateParameter($parameter);
1201 my $parameterName = $parameter->name;
1203 # Optional callbacks should be treated differently, because they always have a default value (0),
1204 # and we can reduce the number of overloaded functions that take a different number of parameters.
1205 if ($parameter->extendedAttributes->{"Optional"} && !$parameter->extendedAttributes->{"Callback"}) {
1206 # Generate early call if there are not enough parameters.
1207 push(@implContentDecls, " if (args.Length() <= $paramIndex) {\n");
1208 my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName);
1209 push(@implContentDecls, $functionCall);
1210 push(@implContentDecls, " }\n");
1213 if (BasicTypeCanFailConversion($parameter)) {
1214 push(@implContentDecls, " bool ${parameterName}Ok;\n");
1217 $implIncludes{"ExceptionCode.h"} = 1;
1218 my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1219 if ($parameter->extendedAttributes->{"Callback"}) {
1220 my $className = GetCallbackClassName($parameter->type);
1221 $implIncludes{"$className.h"} = 1;
1222 if ($parameter->extendedAttributes->{"Optional"}) {
1223 push(@implContentDecls, " RefPtr<" . $parameter->type . "> $parameterName;\n");
1224 push(@implContentDecls, " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n");
1225 push(@implContentDecls, " if (!args[$paramIndex]->IsObject())\n");
1226 push(@implContentDecls, " return throwError(TYPE_MISMATCH_ERR);\n");
1227 push(@implContentDecls, " $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n");
1228 push(@implContentDecls, " }\n");
1230 push(@implContentDecls, " if (args.Length() <= $paramIndex || !args[$paramIndex]->IsObject())\n");
1231 push(@implContentDecls, " return throwError(TYPE_MISMATCH_ERR);\n");
1232 push(@implContentDecls, " RefPtr<" . $parameter->type . "> $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n");
1234 } elsif ($parameter->type eq "SerializedScriptValue") {
1235 $implIncludes{"SerializedScriptValue.h"} = 1;
1236 push(@implContentDecls, " bool ${parameterName}DidThrow = false;\n");
1237 push(@implContentDecls, " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n");
1238 push(@implContentDecls, " if (${parameterName}DidThrow)\n");
1239 push(@implContentDecls, " return v8::Undefined();\n");
1240 } elsif (TypeCanFailConversion($parameter)) {
1241 push(@implContentDecls, " $nativeType $parameterName = " .
1242 JSValueToNative($parameter, "args[$paramIndex]", BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n");
1243 push(@implContentDecls, " if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n");
1244 push(@implContentDecls, " ec = TYPE_MISMATCH_ERR;\n");
1245 push(@implContentDecls, " goto fail;\n");
1246 push(@implContentDecls, " }\n");
1247 } elsif ($nativeType =~ /^V8Parameter/) {
1248 my $value = JSValueToNative($parameter, "args[$paramIndex]", BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef);
1249 push(@implContentDecls, " " . ConvertToV8Parameter($parameter, $nativeType, $parameterName, $value) . "\n");
1251 $implIncludes{"V8BindingMacros.h"} = 1;
1252 # For functions with "StrictTypeChecking", if an input parameter's type does not match the signature,
1253 # a TypeError is thrown instead of casting to null.
1254 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1255 my $argValue = "args[$paramIndex]";
1256 my $argType = GetTypeFromSignature($parameter);
1257 if (IsWrapperType($argType)) {
1258 push(@implContentDecls, " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue)) {\n");
1259 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1260 push(@implContentDecls, " return notHandledByInterceptor();\n");
1261 push(@implContentDecls, " }\n");
1262 } elsif ($codeGenerator->IsStringType($argType)) {
1263 push(@implContentDecls, " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !${argValue}->IsString() && !${argValue}->IsObject()) {\n");
1264 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1265 push(@implContentDecls, " return notHandledByInterceptor();\n");
1266 push(@implContentDecls, " }\n");
1269 push(@implContentDecls, " EXCEPTION_BLOCK($nativeType, $parameterName, " .
1270 JSValueToNative($parameter, "args[$paramIndex]", BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ");\n");
1273 if ($parameter->extendedAttributes->{"IsIndex"}) {
1274 push(@implContentDecls, " if (UNLIKELY($parameterName < 0)) {\n");
1275 push(@implContentDecls, " ec = INDEX_SIZE_ERR;\n");
1276 push(@implContentDecls, " goto fail;\n");
1277 push(@implContentDecls, " }\n");
1283 # Build the function call string.
1284 my $callString = GenerateFunctionCallString($function, $paramIndex, " ", $implClassName);
1285 push(@implContentDecls, "$callString");
1287 if ($raisesExceptions) {
1288 push(@implContentDecls, " }\n");
1289 push(@implContentDecls, " fail:\n");
1290 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
1291 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1294 push(@implContentDecls, "}\n\n");
1297 sub GenerateBatchedAttributeData
1299 my $dataNode = shift;
1300 my $interfaceName = $dataNode->name;
1301 my $attributes = shift;
1303 foreach my $attribute (@$attributes) {
1304 my $conditionalString = GenerateConditionalString($attribute->signature);
1305 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1306 GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1307 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
1311 sub GenerateSingleBatchedAttribute
1313 my $interfaceName = shift;
1314 my $attribute = shift;
1315 my $delimiter = shift;
1317 my $attrName = $attribute->signature->name;
1318 my $attrExt = $attribute->signature->extendedAttributes;
1320 # Attributes of type SerializedScriptValue are set in the
1321 # constructor and don't require callbacks.
1322 return if ($attribute->signature->type eq "SerializedScriptValue");
1324 my $accessControl = "v8::DEFAULT";
1325 if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1326 $accessControl = "v8::ALL_CAN_READ";
1327 } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1328 $accessControl = "v8::ALL_CAN_WRITE";
1329 } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1330 $accessControl = "v8::ALL_CAN_READ";
1331 if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1332 $accessControl .= " | v8::ALL_CAN_WRITE";
1335 if ($attrExt->{"V8DisallowShadowing"}) {
1336 $accessControl .= " | v8::PROHIBITS_OVERWRITING";
1338 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1340 my $customAccessor =
1341 $attrExt->{"Custom"} ||
1342 $attrExt->{"CustomSetter"} ||
1343 $attrExt->{"CustomGetter"} ||
1344 $attrExt->{"V8Custom"} ||
1345 $attrExt->{"V8CustomSetter"} ||
1346 $attrExt->{"V8CustomGetter"} ||
1348 if ($customAccessor eq 1) {
1349 # use the naming convension, interface + (capitalize) attr name
1350 $customAccessor = $interfaceName . "::" . $attrName;
1355 my $propAttr = "v8::None";
1356 my $hasCustomSetter = 0;
1359 if ($attrExt->{"DontEnum"}) {
1360 $propAttr .= " | v8::DontEnum";
1362 if ($attrExt->{"V8DisallowShadowing"}) {
1363 $propAttr .= " | v8::DontDelete";
1366 my $on_proto = "0 /* on instance */";
1367 my $data = "0 /* no data */";
1370 if ($attribute->signature->type =~ /Constructor$/) {
1371 my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1372 $constructorType =~ s/Constructor$//;
1373 $implIncludes{"V8${constructorType}.h"} = 1;
1374 if ($customAccessor) {
1375 $getter = "V8${customAccessor}AccessorGetter";
1377 $data = "&V8${constructorType}::info";
1378 $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1381 $propAttr = "v8::ReadOnly";
1384 # Default Getter and Setter
1385 $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1386 $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1389 if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1390 $hasCustomSetter = 1;
1391 $setter = "V8${customAccessor}AccessorSetter";
1395 if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1396 $getter = "V8${customAccessor}AccessorGetter";
1401 if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1403 # Handle the special case of window.top being marked as Replaceable.
1404 # FIXME: Investigate whether we could treat window.top as replaceable
1405 # and allow shadowing without it being a security hole.
1406 if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1407 $propAttr .= " | v8::ReadOnly";
1411 # Read only attributes
1412 if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1416 # An accessor can be installed on the proto
1417 if ($attrExt->{"v8OnProto"}) {
1418 $on_proto = "1 /* on proto */";
1421 my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1422 "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1424 push(@implContent, $indent . " \/\/ $commentInfo\n");
1425 push(@implContent, $indent . " {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
1428 sub GenerateImplementationIndexer
1430 my $dataNode = shift;
1431 my $indexer = shift;
1432 my $interfaceName = $dataNode->name;
1434 # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files.
1435 my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"};
1436 my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1438 # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
1439 if ($interfaceName eq "HTMLOptionsCollection") {
1442 # FIXME: If the parent interface of $dataNode already has
1443 # HasIndexGetter, we don't need to handle the getter here.
1444 if ($interfaceName eq "WebKitCSSTransformValue") {
1448 # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
1449 # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
1450 # simplistic, mirrored indexer handling in addition to named property handling.
1451 my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
1452 if ($isSpecialCase) {
1454 if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) {
1455 $hasCustomSetter = 1;
1463 $implIncludes{"V8Collection.h"} = 1;
1465 my $indexerType = $indexer ? $indexer->type : 0;
1467 # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
1468 if ($interfaceName eq "WebKitCSSKeyframesRule") {
1469 $indexerType = "WebKitCSSKeyframeRule";
1472 if ($indexerType && !$hasCustomSetter) {
1473 if ($indexerType eq "DOMString") {
1474 my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
1475 if ($conversion && $conversion eq "Null") {
1476 push(@implContent, <<END);
1477 setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
1480 push(@implContent, <<END);
1481 setCollectionStringIndexedGetter<${interfaceName}>(desc);
1485 push(@implContent, <<END);
1486 setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
1488 # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
1489 $implIncludes{"V8${indexerType}.h"} = 1;
1495 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1496 my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
1497 my $setOn = "Instance";
1499 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1500 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1501 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1503 if ($interfaceName eq "DOMWindow") {
1504 $setOn = "Prototype";
1508 push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
1509 push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
1510 push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
1511 push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
1512 push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
1513 push(@implContent, ");\n");
1516 sub GenerateImplementationNamedPropertyGetter
1518 my $dataNode = shift;
1519 my $namedPropertyGetter = shift;
1520 my $interfaceName = $dataNode->name;
1521 my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
1523 # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
1524 # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
1525 if ($interfaceName eq "HTMLOptionsCollection") {
1526 $interfaceName = "HTMLCollection";
1527 $hasCustomGetter = 1;
1530 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
1531 $hasCustomGetter = 1;
1534 if ($interfaceName eq "HTMLDocument") {
1535 $hasCustomGetter = 0;
1538 my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter;
1543 if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) {
1544 $implIncludes{"V8Collection.h"} = 1;
1545 my $type = $namedPropertyGetter->type;
1546 push(@implContent, <<END);
1547 setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
1552 my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"};
1553 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
1554 my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
1555 my $setOn = "Instance";
1557 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
1558 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
1559 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
1561 if ($interfaceName eq "DOMWindow") {
1562 $setOn = "Prototype";
1567 push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
1568 push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
1569 # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
1570 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyQuery, " : "0, ");
1571 push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
1572 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
1573 push(@implContent, ");\n");
1576 sub GenerateImplementationCustomCall
1578 my $dataNode = shift;
1579 my $interfaceName = $dataNode->name;
1580 my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
1582 # FIXME: Remove hard-coded HTMLOptionsCollection reference.
1583 if ($interfaceName eq "HTMLOptionsCollection") {
1584 $interfaceName = "HTMLCollection";
1588 if ($hasCustomCall) {
1589 push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
1593 sub GenerateImplementationMasqueradesAsUndefined
1595 my $dataNode = shift;
1596 if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
1598 push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n");
1602 sub GenerateImplementation
1605 my $dataNode = shift;
1606 my $interfaceName = $dataNode->name;
1607 my $visibleInterfaceName = GetVisibleInterfaceName($interfaceName);
1608 my $className = "V8$interfaceName";
1609 my $implClassName = $interfaceName;
1611 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1613 # - Add default header template
1614 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
1616 $implIncludes{"RuntimeEnabledFeatures.h"} = 1;
1617 $implIncludes{"V8Proxy.h"} = 1;
1618 $implIncludes{"V8Binding.h"} = 1;
1619 $implIncludes{"V8BindingState.h"} = 1;
1620 $implIncludes{"V8DOMWrapper.h"} = 1;
1621 $implIncludes{"V8IsolatedContext.h"} = 1;
1623 if ($className =~ /^V8SVGAnimated/) {
1624 AddIncludesForSVGAnimatedType($interfaceName);
1627 AddIncludesForType($interfaceName);
1629 my $toActive = IsActiveDomType($interfaceName) ? "${className}::toActiveDOMObject" : "0";
1631 push(@implContentDecls, "namespace WebCore {\n\n");
1632 push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive} };\n\n");
1633 push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1634 push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1636 my $hasConstructors = 0;
1637 my $serializedAttribute;
1638 # Generate property accessors for attributes.
1639 for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1640 $attribute = @{$dataNode->attributes}[$index];
1641 $attrName = $attribute->signature->name;
1642 $attrType = $attribute->signature->type;
1644 # Generate special code for the constructor attributes.
1645 if ($attrType =~ /Constructor$/) {
1646 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1647 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1648 $hasConstructors = 1;
1653 if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1654 $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1657 # Attributes of type SerializedScriptValue are set in the
1658 # constructor and don't require callbacks.
1659 if ($attrType eq "SerializedScriptValue") {
1660 die "Only one attribute of type SerializedScriptValue supported" if $serializedAttribute;
1661 $implIncludes{"SerializedScriptValue.h"} = 1;
1662 $serializedAttribute = $attribute;
1666 # Do not generate accessor if this is a custom attribute. The
1667 # call will be forwarded to a hand-written accessor
1669 if ($attribute->signature->extendedAttributes->{"Custom"} ||
1670 $attribute->signature->extendedAttributes->{"V8Custom"}) {
1674 # Generate the accessor.
1675 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
1676 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
1677 GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
1679 if (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
1680 !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
1681 !$attribute->signature->extendedAttributes->{"Replaceable"} &&
1682 $attribute->type !~ /^readonly/ &&
1683 !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1684 GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
1688 if ($hasConstructors) {
1689 GenerateConstructorGetter($implClassName);
1692 $codeGenerator->LinkOverloadedFunctions($dataNode);
1695 my $namedPropertyGetter;
1696 # Generate methods for functions.
1697 foreach my $function (@{$dataNode->functions}) {
1698 if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) {
1699 GenerateFunctionCallback($function, $dataNode, $implClassName);
1700 if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
1701 GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName);
1705 if ($function->signature->name eq "item") {
1706 $indexer = $function->signature;
1709 if ($function->signature->name eq "namedItem") {
1710 $namedPropertyGetter = $function->signature;
1713 # If the function does not need domain security check, we need to
1714 # generate an access getter that returns different function objects
1715 # for different calling context.
1716 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1717 GenerateDomainSafeFunctionGetter($function, $implClassName);
1722 my $attributes = $dataNode->attributes;
1724 # For the DOMWindow interface we partition the attributes into the
1725 # ones that disallows shadowing and the rest.
1726 my @disallowsShadowing;
1727 # Also separate out attributes that are enabled at runtime so we can process them specially.
1728 my @enabledAtRuntime;
1730 foreach my $attribute (@$attributes) {
1732 if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1733 push(@disallowsShadowing, $attribute);
1734 } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1735 push(@enabledAtRuntime, $attribute);
1737 push(@normal, $attribute);
1740 $attributes = \@normal;
1741 # Put the attributes that disallow shadowing on the shadow object.
1742 if (@disallowsShadowing) {
1743 push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n");
1744 GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1745 push(@implContent, "};\n");
1748 my $has_attributes = 0;
1750 $has_attributes = 1;
1751 push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n");
1752 GenerateBatchedAttributeData($dataNode, $attributes);
1753 push(@implContent, "};\n");
1756 # Setup table of standard callback functions
1759 foreach my $function (@{$dataNode->functions}) {
1760 # Only one table entry is needed for overloaded methods:
1761 next if $function->{overloadIndex} > 1;
1763 my $attrExt = $function->signature->extendedAttributes;
1764 # Don't put any nonstandard functions into this table:
1765 if ($attrExt->{"V8OnInstance"}) {
1768 if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1771 if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1772 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1775 if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1778 if (!$has_callbacks) {
1780 push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n");
1782 my $name = $function->signature->name;
1783 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1784 push(@implContent, <<END);
1785 {"$name", $callback},
1789 push(@implContent, "};\n") if $has_callbacks;
1792 my $has_constants = 0;
1793 if (@{$dataNode->constants}) {
1795 push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n");
1797 foreach my $constant (@{$dataNode->constants}) {
1798 my $name = $constant->name;
1799 my $value = $constant->value;
1800 # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
1801 # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we
1802 # handled this here, and converted it to a -1 constant in the c++ output.
1803 push(@implContent, <<END);
1804 {"${name}", static_cast<signed int>($value)},
1807 if ($has_constants) {
1808 push(@implContent, "};\n");
1809 push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
1812 push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
1814 # In namespace WebCore, add generated implementation for 'CanBeConstructed'.
1815 if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"} && !$dataNode->extendedAttributes->{"V8CustomConstructor"}) {
1816 my $v8ConstructFunction;
1817 my $callWith = $dataNode->extendedAttributes->{"CallWith"};
1818 if ($callWith and $callWith eq "ScriptExecutionContext") {
1819 $v8ConstructFunction = "constructDOMObjectWithScriptExecutionContext";
1821 $v8ConstructFunction = "constructDOMObject";
1823 push(@implContent, <<END);
1824 v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args)
1826 INC_STATS("DOM.${interfaceName}.Contructor");
1827 return V8Proxy::${v8ConstructFunction}<$interfaceName>(args, &info);
1832 my $access_check = "";
1833 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
1834 $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));";
1837 # For the DOMWindow interface, generate the shadow object template
1838 # configuration method.
1839 if ($implClassName eq "DOMWindow") {
1840 push(@implContent, <<END);
1841 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
1843 batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, sizeof(shadowAttrs) / sizeof(*shadowAttrs));
1845 // Install a security handler with V8.
1846 templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info));
1847 templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
1853 # find the super descriptor
1854 my $parentClassTemplate = "";
1855 foreach (@{$dataNode->parents}) {
1856 my $parent = $codeGenerator->StripModule($_);
1857 if ($parent eq "EventTarget") { next; }
1858 $implIncludes{"V8${parent}.h"} = 1;
1859 $parentClassTemplate = "V8" . $parent . "::GetTemplate()";
1862 if (!$parentClassTemplate) {
1863 $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
1866 # Generate the template configuration method
1867 push(@implContent, <<END);
1868 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc)
1870 v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount,
1872 # Set up our attributes if we have them
1873 if ($has_attributes) {
1874 push(@implContent, <<END);
1875 ${interfaceName}Attrs, sizeof(${interfaceName}Attrs) / sizeof(*${interfaceName}Attrs),
1878 push(@implContent, <<END);
1883 if ($has_callbacks) {
1884 push(@implContent, <<END);
1885 ${interfaceName}Callbacks, sizeof(${interfaceName}Callbacks) / sizeof(*${interfaceName}Callbacks));
1888 push(@implContent, <<END);
1893 if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) {
1894 push(@implContent, <<END);
1895 desc->SetCallHandler(V8${interfaceName}::constructorCallback);
1899 if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
1900 push(@implContent, <<END);
1901 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
1902 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
1906 push(@implContent, " $access_check\n");
1908 # Setup the enable-at-runtime attrs if we have them
1909 foreach my $runtime_attr (@enabledAtRuntime) {
1910 # A function named RuntimeEnabledFeatures::{methodName}Enabled() need to be written by hand.
1911 $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($runtime_attr->signature->name) . "Enabled";
1912 my $conditionalString = GenerateConditionalString($runtime_attr->signature);
1913 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1914 push(@implContent, " if (${enable_function}()) {\n");
1915 push(@implContent, " static const BatchedAttribute attrData =\\\n");
1916 GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " ");
1917 push(@implContent, <<END);
1918 configureAttribute(instance, proto, attrData);
1921 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1924 GenerateImplementationIndexer($dataNode, $indexer);
1925 GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
1926 GenerateImplementationCustomCall($dataNode);
1927 GenerateImplementationMasqueradesAsUndefined($dataNode);
1929 # Define our functions with Set() or SetAccessor()
1930 $total_functions = 0;
1931 foreach my $function (@{$dataNode->functions}) {
1932 # Only one accessor is needed for overloaded methods:
1933 next if $function->{overloadIndex} > 1;
1936 my $attrExt = $function->signature->extendedAttributes;
1937 my $name = $function->signature->name;
1939 my $property_attributes = "v8::DontDelete";
1940 if ($attrExt->{"DontEnum"}) {
1941 $property_attributes .= " | v8::DontEnum";
1943 if ($attrExt->{"V8ReadOnly"}) {
1944 $property_attributes .= " | v8::ReadOnly";
1947 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1949 my $template = "proto";
1950 if ($attrExt->{"V8OnInstance"}) {
1951 $template = "instance";
1954 my $conditional = "";
1955 if ($attrExt->{"EnabledAtRuntime"}) {
1956 # Only call Set()/SetAccessor() if this method should be enabled
1957 $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($function->signature->name) . "Enabled";
1958 $conditional = "if (${enable_function}())\n ";
1961 if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1962 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1963 # Mark the accessor as ReadOnly and set it on the proto object so
1964 # it can be shadowed. This is really a hack to make it work.
1965 # There are several sceneria to call into the accessor:
1966 # 1) from the same domain: "window.open":
1967 # the accessor finds the DOM wrapper in the proto chain;
1968 # 2) from the same domain: "window.__proto__.open":
1969 # the accessor will NOT find a DOM wrapper in the prototype chain
1970 # 3) from another domain: "window.open":
1971 # the access find the DOM wrapper in the prototype chain
1972 # "window.__proto__.open" from another domain will fail when
1973 # accessing '__proto__'
1975 # The solution is very hacky and fragile, it really needs to be replaced
1976 # by a better solution.
1977 $property_attributes .= " | v8::ReadOnly";
1978 push(@implContent, <<END);
1981 ${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));
1987 my $signature = "defaultSignature";
1988 if ($attrExt->{"V8DoNotCheckSignature"}) {
1989 $signature = "v8::Local<v8::Signature>()";
1992 if (RequiresCustomSignature($function)) {
1993 $signature = "${name}Signature";
1994 push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function));
1997 # Normal function call is a template
1998 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2000 if ($property_attributes eq "v8::DontDelete") {
2001 $property_attributes = "";
2003 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2006 if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2007 # Standard type of callback, already created in the batch, so skip it here.
2011 push(@implContent, <<END);
2012 ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);
2017 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
2019 if ($has_constants) {
2020 push(@implContent, <<END);
2021 batchConfigureConstants(desc, proto, ${interfaceName}Consts, sizeof(${interfaceName}Consts) / sizeof(*${interfaceName}Consts));
2026 if ($interfaceName eq "DOMWindow") {
2027 push(@implContent, <<END);
2029 proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2030 desc->SetHiddenPrototype(true);
2031 instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2032 // Set access check callbacks, but turned off initially.
2033 // When a context is detached from a frame, turn on the access check.
2034 // Turning on checks also invalidates inline caches of the object.
2035 instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false);
2038 if ($interfaceName eq "HTMLDocument") {
2039 push(@implContent, <<END);
2040 desc->SetHiddenPrototype(true);
2043 if ($interfaceName eq "Location") {
2044 push(@implContent, <<END);
2046 // For security reasons, these functions are on the instance instead
2047 // of on the prototype object to ensure that they cannot be overwritten.
2048 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));
2049 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));
2050 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));
2054 my $nativeType = GetNativeTypeForConversions($interfaceName);
2055 if ($dataNode->extendedAttributes->{"PODType"}) {
2056 $nativeType = "V8SVGPODTypeWrapper<${nativeType}>";
2058 push(@implContent, <<END);
2060 // Custom toString template
2061 desc->Set(getToStringName(), getToStringTemplate());
2065 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate()
2067 static v8::Persistent<v8::FunctionTemplate> ${className}RawCache = createRawTemplate();
2068 return ${className}RawCache;
2071 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()\
2073 static v8::Persistent<v8::FunctionTemplate> ${className}Cache = Configure${className}Template(GetRawTemplate());
2074 return ${className}Cache;
2077 ${nativeType}* ${className}::toNative(v8::Handle<v8::Object> object)
2079 return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
2082 bool ${className}::HasInstance(v8::Handle<v8::Value> value)
2084 return GetRawTemplate()->HasInstance(value);
2089 if (IsActiveDomType($interfaceName)) {
2090 # MessagePort is handled like an active dom object even though it doesn't inherit
2091 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
2092 my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
2093 push(@implContent, <<END);
2094 ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object)
2096 return ${returnValue};
2101 if ($implClassName eq "DOMWindow") {
2102 push(@implContent, <<END);
2103 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
2105 static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
2106 if (V8DOMWindowShadowObjectCache.IsEmpty()) {
2107 V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
2108 ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
2110 return V8DOMWindowShadowObjectCache;
2115 GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType, $serializedAttribute);
2117 push(@implContent, <<END);
2119 void ${className}::derefObject(void* object)
2123 if (IsRefPtrType($interfaceName)) {
2124 push(@implContent, <<END);
2125 static_cast<${nativeType}*>(object)->deref();
2129 push(@implContent, <<END);
2132 } // namespace WebCore
2135 my $conditionalString = GenerateConditionalString($dataNode);
2136 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2138 # We've already added the header for this file in implFixedHeader, so remove
2139 # it from implIncludes to ensure we don't #include it twice.
2140 delete $implIncludes{"${className}.h"};
2143 sub GenerateHeaderContentHeader
2145 my $dataNode = shift;
2146 my $className = "V8" . $dataNode->name;
2147 my $conditionalString = GenerateConditionalString($dataNode);
2149 my @headerContentHeader = split("\r", $headerTemplate);
2151 push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
2152 push(@headerContentHeader, "\n#ifndef ${className}" . "_h");
2153 push(@headerContentHeader, "\n#define ${className}" . "_h\n\n");
2154 return @headerContentHeader;
2157 sub GenerateImplementationContentHeader
2159 my $dataNode = shift;
2160 my $className = "V8" . $dataNode->name;
2161 my $conditionalString = GenerateConditionalString($dataNode);
2163 my @implContentHeader = split("\r", $headerTemplate);
2165 push(@implContentHeader, "\n#include \"config.h\"\n");
2166 push(@implContentHeader, "#include \"${className}.h\"\n\n");
2167 push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
2168 return @implContentHeader;
2171 sub GenerateCallbackHeader
2174 my $dataNode = shift;
2176 my $interfaceName = $dataNode->name;
2177 my $className = "V8$interfaceName";
2180 # - Add default header template
2181 push(@headerContent, GenerateHeaderContentHeader($dataNode));
2183 my @unsortedIncludes = ();
2184 push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\"");
2185 push(@unsortedIncludes, "#include \"$interfaceName.h\"");
2186 push(@unsortedIncludes, "#include \"WorldContextHandle.h\"");
2187 push(@unsortedIncludes, "#include <v8.h>");
2188 push(@unsortedIncludes, "#include <wtf/Forward.h>");
2189 push(@headerContent, join("\n", sort @unsortedIncludes));
2191 push(@headerContent, "\n\nnamespace WebCore {\n\n");
2192 push(@headerContent, "class ScriptExecutionContext;\n\n");
2193 push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
2195 push(@headerContent, <<END);
2197 static PassRefPtr<${className}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
2199 ASSERT(value->IsObject());
2201 return adoptRef(new ${className}(value->ToObject(), context));
2204 virtual ~${className}();
2209 my $numFunctions = @{$dataNode->functions};
2210 if ($numFunctions > 0) {
2211 push(@headerContent, " // Functions\n");
2212 foreach my $function (@{$dataNode->functions}) {
2213 my @params = @{$function->parameters};
2214 if (!$function->signature->extendedAttributes->{"Custom"} &&
2215 !(GetNativeType($function->signature->type) eq "bool")) {
2216 push(@headerContent, " COMPILE_ASSERT(false)");
2219 push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
2222 foreach my $param (@params) {
2223 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2225 push(@headerContent, join(", ", @args));
2226 push(@headerContent, ");\n");
2230 push(@headerContent, <<END);
2233 ${className}(v8::Local<v8::Object>, ScriptExecutionContext*);
2235 v8::Persistent<v8::Object> m_callback;
2236 WorldContextHandle m_worldContext;
2241 push(@headerContent, "}\n\n");
2242 push(@headerContent, "#endif // $className" . "_h\n\n");
2244 my $conditionalString = GenerateConditionalString($dataNode);
2245 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
2248 sub GenerateCallbackImplementation
2251 my $dataNode = shift;
2252 my $interfaceName = $dataNode->name;
2253 my $className = "V8$interfaceName";
2255 # - Add default header template
2256 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2258 $implIncludes{"ScriptExecutionContext.h"} = 1;
2259 $implIncludes{"V8CustomVoidCallback.h"} = 1;
2260 $implIncludes{"V8Proxy.h"} = 1;
2262 push(@implContent, "#include <wtf/Assertions.h>\n\n");
2263 push(@implContent, "namespace WebCore {\n\n");
2264 push(@implContent, <<END);
2265 ${className}::${className}(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
2266 : ActiveDOMCallback(context)
2267 , m_callback(v8::Persistent<v8::Object>::New(callback))
2268 , m_worldContext(UseCurrentWorld)
2272 ${className}::~${className}()
2274 m_callback.Dispose();
2280 my $numFunctions = @{$dataNode->functions};
2281 if ($numFunctions > 0) {
2282 push(@implContent, "// Functions\n");
2283 foreach my $function (@{$dataNode->functions}) {
2284 my @params = @{$function->parameters};
2285 if ($function->signature->extendedAttributes->{"Custom"} ||
2286 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
2290 AddIncludesForType($function->signature->type);
2291 push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(");
2294 foreach my $param (@params) {
2295 AddIncludesForType($param->type);
2296 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2298 push(@implContent, join(", ", @args));
2300 push(@implContent, ")\n");
2301 push(@implContent, "{\n");
2302 push(@implContent, " if (!canInvokeCallback())\n");
2303 push(@implContent, " return true;\n\n");
2304 push(@implContent, " v8::HandleScope handleScope;\n\n");
2305 push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n");
2306 push(@implContent, " if (v8Context.IsEmpty())\n");
2307 push(@implContent, " return true;\n\n");
2308 push(@implContent, " v8::Context::Scope scope(v8Context);\n\n");
2311 foreach my $param (@params) {
2312 my $paramName = $param->name;
2313 push(@implContent, " v8::Handle<v8::Value> ${paramName}Handle = toV8(${paramName});\n");
2314 push(@implContent, " if (${paramName}Handle.IsEmpty()) {\n");
2315 push(@implContent, " CRASH();\n");
2316 push(@implContent, " return true;\n");
2317 push(@implContent, " }\n");
2318 push(@args, " ${paramName}Handle");
2321 push(@implContent, "\n v8::Handle<v8::Value> argv[] = {\n");
2322 push(@implContent, join(",\n", @args));
2323 push(@implContent, "\n };\n\n");
2324 push(@implContent, " bool callbackReturnValue = false;\n");
2325 push(@implContent, " return !invokeCallback(m_callback, " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
2326 push(@implContent, "}\n");
2330 push(@implContent, "\n} // namespace WebCore\n\n");
2332 my $conditionalString = GenerateConditionalString($dataNode);
2333 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2336 sub GenerateToV8Converters
2338 my $dataNode = shift;
2339 my $interfaceName = shift;
2340 my $className = shift;
2341 my $nativeType = shift;
2342 my $serializedAttribute = shift;
2344 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
2345 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
2346 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
2348 push(@implContent, <<END);
2350 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput})
2352 v8::Handle<v8::Object> wrapper;
2356 if (IsNodeSubType($dataNode)) {
2357 push(@implContent, <<END);
2358 if (impl->document()) {
2359 proxy = V8Proxy::retrieve(impl->document()->frame());
2360 if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl))
2361 proxy->windowShell()->initContextIfNeeded();
2367 if ($domMapFunction) {
2368 push(@implContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
2369 if (IsNodeSubType($dataNode)) {
2370 push(@implContent, " wrapper = V8DOMWrapper::getWrapper(impl);\n");
2372 push(@implContent, " wrapper = ${domMapFunction}.get(impl);\n");
2374 push(@implContent, <<END);
2375 if (!wrapper.IsEmpty())
2378 push(@implContent, " }\n") if IsDOMNodeType($interfaceName);
2380 if (IsNodeSubType($dataNode)) {
2381 push(@implContent, <<END);
2383 v8::Handle<v8::Context> context;
2385 context = proxy->context();
2387 // Enter the node's context and create the wrapper in that context.
2388 if (!context.IsEmpty())
2393 push(@implContent, <<END);
2394 wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl);
2396 if (IsNodeSubType($dataNode)) {
2397 push(@implContent, <<END);
2398 // Exit the node's context if it was entered.
2399 if (!context.IsEmpty())
2404 push(@implContent, <<END);
2405 if (wrapper.IsEmpty())
2408 push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName);
2410 # Eagerly deserialize attributes of type SerializedScriptValue
2411 # while we're in the right context.
2412 if ($serializedAttribute) {
2413 die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue";
2414 my $attrName = $serializedAttribute->signature->name;
2415 my $attrAttr = "v8::DontDelete";
2416 if ($serializedAttribute->type =~ /^readonly/) {
2417 $attrAttr .= " | v8::ReadOnly";
2419 $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)";
2420 my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
2421 push(@implContent, <<END);
2422 SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}());
2426 if ($domMapFunction) {
2427 push(@implContent, <<END);
2428 ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper));
2432 push(@implContent, <<END);
2437 if (IsRefPtrType($interfaceName)) {
2438 push(@implContent, <<END);
2440 v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl${forceNewObjectInput})
2442 return toV8(impl.get()${forceNewObjectCall});
2447 if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
2448 push(@implContent, <<END);
2450 v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectInput})
2454 return ${className}::wrap(impl${forceNewObjectCall});
2460 sub HasCustomToV8Implementation {
2461 # FIXME: This subroutine is lame. Probably should be an .idl attribute (CustomToV8)?
2463 $interfaceName = shift;
2465 # We generate a custom converter (but JSC doesn't) for the following:
2466 return 1 if $interfaceName eq "CSSStyleSheet";
2467 return 1 if $interfaceName eq "CanvasPixelArray";
2468 return 1 if $interfaceName eq "DOMWindow";
2469 return 1 if $interfaceName eq "Element";
2470 return 1 if $interfaceName eq "HTMLDocument";
2471 return 1 if $interfaceName eq "HTMLElement";
2472 return 1 if $interfaceName eq "Location";
2473 return 1 if $interfaceName eq "NamedNodeMap";
2474 return 1 if $interfaceName eq "SVGDocument";
2475 return 1 if $interfaceName eq "SVGElement";
2476 return 1 if $interfaceName eq "ScriptProfile";
2477 return 1 if $interfaceName eq "ScriptProfileNode";
2478 return 1 if $interfaceName eq "WorkerContext";
2479 # We don't generate a custom converter (but JSC does) for the following:
2480 return 0 if $interfaceName eq "AbstractWorker";
2481 return 0 if $interfaceName eq "CanvasRenderingContext";
2482 return 0 if $interfaceName eq "ImageData";
2483 return 0 if $interfaceName eq "SVGElementInstance";
2485 # For everything else, do what JSC does.
2486 return $dataNode->extendedAttributes->{"CustomToJS"};
2489 sub GetDomMapFunction
2491 my $dataNode = shift;
2493 return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
2494 return "getDOMNodeMap()" if ($dataNode && IsNodeSubType($dataNode));
2495 # Only use getDOMSVGObjectWithContextMap() for non-node svg objects
2496 return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/;
2497 return "" if $type eq "DOMImplementation";
2498 return "getActiveDOMObjectMap()" if IsActiveDomType($type);
2499 return "getDOMObjectMap()";
2504 # FIXME: Consider making this an .idl attribute.
2506 return 1 if $type eq "EventSource";
2507 return 1 if $type eq "MessagePort";
2508 return 1 if $type eq "XMLHttpRequest";
2509 return 1 if $type eq "WebSocket";
2510 return 1 if $type eq "Worker";
2511 return 1 if $type eq "SharedWorker";
2512 return 1 if $type eq "IDBRequest";
2516 sub GetNativeTypeForConversions
2519 return "FloatRect" if $type eq "SVGRect";
2520 return "FloatPoint" if $type eq "SVGPoint";
2521 return "AffineTransform" if $type eq "SVGMatrix";
2522 return "float" if $type eq "SVGNumber";
2526 sub GenerateFunctionCallString()
2528 my $function = shift;
2529 my $numberOfParameters = shift;
2531 my $implClassName = shift;
2533 my $name = $function->signature->name;
2534 my $isPodType = IsPodType($implClassName);
2535 my $returnType = GetTypeFromSignature($function->signature);
2536 my $returnsPodType = IsPodType($returnType);
2537 my $nativeReturnType = GetNativeType($returnType, 0);
2540 # Special case: SVG matrix transform methods should not mutate
2541 # the matrix but return a copy
2543 if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
2547 if ($function->signature->extendedAttributes->{"v8implname"}) {
2548 $name = $function->signature->extendedAttributes->{"v8implname"};
2551 if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
2552 $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
2555 my $functionString = "imp->${name}(";
2558 $functionString = "result.${name}(";
2561 my $returnsListItemPodType = 0;
2562 # SVG lists functions that return POD types require special handling
2563 if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
2564 $returnsListItemPodType = 1;
2565 $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
2566 $functionString = "listImp->${name}(";
2570 my $hasScriptState = 0;
2572 my $callWith = $function->signature->extendedAttributes->{"CallWith"};
2574 my $callWithArg = "COMPILE_ASSERT(false)";
2575 if ($callWith eq "DynamicFrame") {
2576 $result .= $indent . "Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext();\n";
2577 $result .= $indent . "if (!enteredFrame)\n";
2578 $result .= $indent . " return v8::Undefined();\n";
2579 $callWithArg = "enteredFrame";
2580 } elsif ($callWith eq "ScriptState") {
2581 $result .= $indent . "EmptyScriptState state;\n";
2582 $callWithArg = "&state";
2583 $hasScriptState = 1;
2584 } elsif ($callWith eq "ScriptExecutionContext") {
2585 $result .= $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n";
2586 $result .= $indent . "if (!scriptContext)\n";
2587 $result .= $indent . " return v8::Undefined();\n";
2588 $callWithArg = "scriptContext";
2590 $functionString .= ", " if $index;
2591 $functionString .= $callWithArg;
2593 $numberOfParameters++
2596 foreach my $parameter (@{$function->parameters}) {
2597 if ($index eq $numberOfParameters) {
2600 $functionString .= ", " if $index;
2601 my $paramName = $parameter->name;
2602 my $paramType = $parameter->type;
2604 # This is a bit of a hack... we need to convert parameters to methods on SVG lists
2605 # of POD types which are items in the list to appropriate SVGList<> instances
2606 if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
2607 $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
2610 if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
2611 $functionString .= "$paramName.get()";
2613 $functionString .= $paramName;
2618 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
2619 $functionString .= ", " if $index;
2620 $functionString .= "callStack.get()";
2624 if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
2625 $functionString .= ", " if $index;
2626 # FIXME: We need to pass DOMWrapperWorld as a parameter.
2627 # See http://trac.webkit.org/changeset/54182
2628 $functionString .= "processingUserGesture()";
2632 if (@{$function->raisesExceptions}) {
2633 $functionString .= ", " if $index;
2634 $functionString .= "ec";
2637 $functionString .= ")";
2639 my $return = "result";
2640 my $returnIsRef = IsRefPtrType($returnType);
2642 if ($returnType eq "void") {
2643 $result .= $indent . "$functionString;\n";
2644 } elsif ($copyFirst) {
2645 $result .= $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . $indent . "$functionString;\n";
2646 } elsif ($returnsListItemPodType) {
2647 $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
2648 } elsif ($hasScriptState or @{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
2649 $result .= $indent . $nativeReturnType . " result = $functionString;\n";
2651 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
2652 $return = $functionString;
2656 if (@{$function->raisesExceptions}) {
2657 $result .= $indent . "if (UNLIKELY(ec))\n";
2658 $result .= $indent . " goto fail;\n";
2661 if ($hasScriptState) {
2662 $result .= $indent . "if (state.hadException())\n";
2663 $result .= $indent . " return throwError(state.exception());\n"
2666 # If the return type is a POD type, separate out the wrapper generation
2667 if ($returnsListItemPodType) {
2668 $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
2669 $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
2670 $return = "wrapper";
2671 } elsif ($returnsPodType) {
2672 $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
2673 $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
2674 $return = "wrapper";
2677 my $generatedSVGContextRetrieval = 0;
2678 # If the return type needs an SVG context, output it
2679 if (IsSVGTypeNeedingContextParameter($returnType)) {
2680 $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
2681 $generatedSVGContextRetrieval = 1;
2684 if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
2685 if (!$generatedSVGContextRetrieval) {
2686 $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2687 $generatedSVGContextRetrieval = 1;
2690 $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
2691 $implIncludes{"SVGElement.h"} = 1;
2694 # If the implementing class is a POD type, commit changes
2696 if (!$generatedSVGContextRetrieval) {
2697 $result .= GenerateSVGContextRetrieval($implClassName, $indent);
2698 $generatedSVGContextRetrieval = 1;
2701 $result .= $indent . "impWrapper->commitChange(impInstance, context);\n";
2704 if ($returnsPodType) {
2705 $implIncludes{"V8${returnType}.h"} = 1;
2706 $result .= $indent . "return toV8(wrapper.release());\n";
2708 $return .= ".release()" if ($returnIsRef);
2709 $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
2716 sub GetTypeFromSignature
2718 my $signature = shift;
2720 return $codeGenerator->StripModule($signature->type);
2724 sub GetNativeTypeFromSignature
2726 my $signature = shift;
2727 my $parameterIndex = shift;
2729 my $type = GetTypeFromSignature($signature);
2731 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
2732 # Special-case index arguments because we need to check that they aren't < 0.
2736 $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
2738 if ($parameterIndex >= 0 && $type eq "V8Parameter") {
2740 if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
2741 $mode = "WithUndefinedOrNullCheck";
2742 } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"} || $signature->extendedAttributes->{"Reflect"}) {
2743 $mode = "WithNullCheck";
2755 return 0 if $type eq "boolean";
2756 return 0 if $type eq "float";
2757 return 0 if $type eq "int";
2758 return 0 if $type eq "Date";
2759 return 0 if $type eq "DOMString";
2760 return 0 if $type eq "double";
2761 return 0 if $type eq "short";
2762 return 0 if $type eq "long";
2763 return 0 if $type eq "unsigned";
2764 return 0 if $type eq "unsigned long";
2765 return 0 if $type eq "unsigned short";
2766 return 0 if $type eq "SVGAnimatedPoints";
2774 my $isParameter = shift;
2776 if ($type eq "float" or $type eq "double") {
2780 return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
2781 return "int" if $type eq "int";
2782 return "int" if $type eq "short" or $type eq "unsigned short";
2783 return "unsigned" if $type eq "unsigned long";
2784 return "int" if $type eq "long";
2785 return "long long" if $type eq "long long";
2786 return "unsigned long long" if $type eq "unsigned long long";
2787 return "bool" if $type eq "boolean";
2788 return "String" if $type eq "DOMString";
2789 return "Range::CompareHow" if $type eq "CompareHow";
2790 return "FloatRect" if $type eq "SVGRect";
2791 return "FloatPoint" if $type eq "SVGPoint";
2792 return "AffineTransform" if $type eq "SVGMatrix";
2793 return "SVGTransform" if $type eq "SVGTransform";
2794 return "SVGLength" if $type eq "SVGLength";
2795 return "SVGAngle" if $type eq "SVGAngle";
2796 return "float" if $type eq "SVGNumber";
2797 return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio";
2798 return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
2799 return "DOMTimeStamp" if $type eq "DOMTimeStamp";
2800 return "unsigned" if $type eq "unsigned int";
2801 return "Node*" if $type eq "EventTarget" and $isParameter;
2802 return "double" if $type eq "Date";
2803 return "ScriptValue" if $type eq "DOMObject";
2805 return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack?
2808 return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
2810 return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
2812 return "RefPtr<IDBKey>" if $type eq "IDBKey";
2814 # necessary as resolvers could be constructed on fly.
2815 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
2817 return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
2819 # Default, assume native type is a pointer with same type name as idl type
2823 sub GetNativeTypeForCallbacks
2826 return "const String&" if $type eq "DOMString";
2828 # Callbacks use raw pointers, so pass isParameter = 1
2829 return GetNativeType($type, 1);
2832 sub TranslateParameter
2834 my $signature = shift;
2836 # The IDL uses some pseudo-types which don't really exist.
2837 if ($signature->type eq "TimeoutHandler") {
2838 $signature->type("DOMString");
2842 sub BasicTypeCanFailConversion
2844 my $signature = shift;
2845 my $type = GetTypeFromSignature($signature);
2847 return 1 if $type eq "SVGAngle";
2848 return 1 if $type eq "SVGLength";
2849 return 1 if $type eq "SVGMatrix";
2850 return 1 if $type eq "SVGPoint";
2851 return 1 if $type eq "SVGPreserveAspectRatio";
2852 return 1 if $type eq "SVGRect";
2853 return 1 if $type eq "SVGTransform";
2857 sub TypeCanFailConversion
2859 my $signature = shift;
2861 my $type = GetTypeFromSignature($signature);
2863 $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
2864 return 1 if $type eq "Attr";
2865 return 1 if $type eq "VoidCallback";
2866 return BasicTypeCanFailConversion($signature);
2871 my $signature = shift;
2873 my $okParam = shift;
2874 my $maybeOkParam = $okParam ? ", ${okParam}" : "";
2876 my $type = GetTypeFromSignature($signature);
2878 return "$value" if $type eq "JSObject";
2879 return "$value->BooleanValue()" if $type eq "boolean";
2880 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
2881 return "$value->NumberValue()" if $type eq "SVGNumber";
2883 return "toInt32($value${maybeOkParam})" if $type eq "long";
2884 return "toUInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short";
2885 return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
2886 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
2887 return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
2888 return "toWebCoreDate($value)" if $type eq "Date";
2890 if ($type eq "DOMString" or $type eq "DOMUserData") {
2894 die "Unexpected SerializedScriptValue" if $type eq "SerializedScriptValue";
2896 if ($type eq "IDBKey") {
2897 $implIncludes{"IDBBindingUtilities.h"} = 1;
2898 $implIncludes{"IDBKey.h"} = 1;
2899 return "createIDBKeyFromValue($value)";
2902 if ($type eq "DOMObject") {
2903 $implIncludes{"ScriptValue.h"} = 1;
2904 return "ScriptValue($value)";
2907 if ($type eq "NodeFilter") {
2908 return "V8DOMWrapper::wrapNativeNodeFilter($value)";
2911 if ($type eq "SVGRect") {
2912 $implIncludes{"FloatRect.h"} = 1;
2915 if ($type eq "SVGPoint") {
2916 $implIncludes{"FloatPoint.h"} = 1;
2919 # Default, assume autogenerated type conversion routines
2920 if ($type eq "EventTarget") {
2921 $implIncludes{"V8Node.h"} = 1;
2923 # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
2924 return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2927 if ($type eq "XPathNSResolver") {
2928 return "V8DOMWrapper::getXPathNSResolver($value)";
2931 AddIncludesForType($type);
2933 if (IsDOMNodeType($type)) {
2934 $implIncludes{"V8${type}.h"} = 1;
2936 # Perform type checks on the parameter, if it is expected Node type,
2938 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2940 $implIncludes{"V8$type.h"} = 1;
2942 if (IsPodType($type)) {
2943 my $nativeType = GetNativeType($type);
2944 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2946 return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(&V8${type}::info, $value${maybeOkParam})"
2949 $implIncludes{"V8${type}.h"} = 1;
2951 # Perform type checks on the parameter, if it is expected Node type,
2953 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
2960 return "V8Event.h" if $type eq "DOMTimeStamp";
2961 return "EventListener.h" if $type eq "EventListener";
2962 return "EventTarget.h" if $type eq "EventTarget";
2963 return "SerializedScriptValue.h" if $type eq "SerializedScriptValue";
2964 return "ScriptValue.h" if $type eq "DOMObject";
2965 return "V8${type}.h";
2968 sub CreateCustomSignature
2970 my $function = shift;
2971 my $count = @{$function->parameters};
2972 my $name = $function->signature->name;
2973 my $result = " const int ${name}Argc = ${count};\n" .
2974 " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { ";
2976 foreach my $parameter (@{$function->parameters}) {
2977 if ($first) { $first = 0; }
2978 else { $result .= ", "; }
2979 if (IsWrapperType($parameter->type)) {
2980 if ($parameter->type eq "XPathNSResolver") {
2981 # Special case for XPathNSResolver. All other browsers accepts a callable,
2982 # so, even though it's against IDL, accept objects here.
2983 $result .= "v8::Handle<v8::FunctionTemplate>()";
2985 my $type = $parameter->type;
2986 my $header = GetV8HeaderName($type);
2987 $implIncludes{$header} = 1;
2988 $result .= "V8${type}::GetRawTemplate()";
2991 $result .= "v8::Handle<v8::FunctionTemplate>()";
2995 $result .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n";
3000 sub RequiresCustomSignature
3002 my $function = shift;
3003 # No signature needed for Custom function
3004 if ($function->signature->extendedAttributes->{"Custom"} ||
3005 $function->signature->extendedAttributes->{"V8Custom"}) {
3008 # No signature needed for overloaded function
3009 if (@{$function->{overloads}} > 1) {
3012 # Type checking is performed in the generated code
3013 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
3016 foreach my $parameter (@{$function->parameters}) {
3017 if ($parameter->extendedAttributes->{"Optional"} || $parameter->extendedAttributes->{"Callback"}) {
3022 foreach my $parameter (@{$function->parameters}) {
3023 if (IsWrapperType($parameter->type)) {
3031 # FIXME: Sort this array.
3032 my %non_wrapper_types = (
3036 'unsigned int' => 1,
3038 'unsigned short' => 1,
3040 'unsigned long' => 1,
3043 'unsigned long long' => 1,
3046 'SerializedScriptValue' => 1,
3050 'SVGPreserveAspectRatio' => 1,
3052 'SVGTransform' => 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 if (IsPodType($type)) {
3166 $value = GenerateSVGStaticPodTypeWrapper($type, $value) . ".get()";
3169 return "return toV8($value)";
3172 sub GenerateSVGStaticPodTypeWrapper {
3176 $implIncludes{"V8$type.h"}=1;
3177 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
3179 my $nativeType = GetNativeType($type);
3180 return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
3186 if (defined($IMPL)) {
3187 # Write content to file.
3188 print $IMPL @implContentHeader;
3190 print $IMPL @implFixedHeader;
3192 foreach my $implInclude (sort keys(%implIncludes)) {
3193 my $checkType = $implInclude;
3194 $checkType =~ s/\.h//;
3196 if ($implInclude =~ /wtf/) {
3197 print $IMPL "#include \<$implInclude\>\n";
3199 print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
3204 print $IMPL @implContentDecls;
3205 print $IMPL @implContent;
3210 @implFixedHeader = ();
3211 @implHeaderContent = ();
3212 @implContentDecls = ();
3216 if (defined($HEADER)) {
3217 # Write content to file.
3218 print $HEADER @headerContent;
3222 @headerContent = ();
3226 sub IsSVGTypeNeedingContextParameter
3228 my $implClassName = shift;
3230 if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
3231 return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
3237 sub GenerateSVGContextAssignment
3239 my $srcType = shift;
3243 $result = GenerateSVGContextRetrieval($srcType, $indent);
3244 $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
3249 sub GenerateSVGContextRetrieval
3251 my $srcType = shift;
3254 my $srcIsPodType = IsPodType($srcType);
3256 my $srcObject = "imp";
3257 if ($srcIsPodType) {
3258 $srcObject = "impWrapper";
3263 if (IsSVGTypeNeedingContextParameter($srcType)) {
3264 $contextDecl = "V8Proxy::svgContext($srcObject)";
3266 $contextDecl = $srcObject;
3269 return $indent . "SVGElement* context = $contextDecl;\n";
3272 sub IsSVGListMutator
3274 my $functionName = shift;
3276 return 1 if $functionName eq "clear";
3277 return 1 if $functionName eq "initialize";
3278 return 1 if $functionName eq "insertItemBefore";
3279 return 1 if $functionName eq "replaceItem";
3280 return 1 if $functionName eq "removeItem";
3281 return 1 if $functionName eq "appendItem";
3288 my $functionName = shift;
3290 return 1 if $functionName eq "getFirst";
3291 return 1 if $functionName eq "getLast";
3292 return 1 if $functionName eq "getItem";
3294 return IsSVGListMutator($functionName);
3297 sub IsSVGListTypeNeedingSpecialHandling
3299 my $className = shift;
3301 return 1 if $className eq "SVGPointList";
3302 return 1 if $className eq "SVGTransformList";
3307 sub GetVisibleInterfaceName
3309 my $interfaceName = shift;
3311 return "DOMException" if $interfaceName eq "DOMCoreException";
3312 return "FormData" if $interfaceName eq "DOMFormData";
3313 return $interfaceName;
3316 sub GetCallbackClassName
3318 my $interfaceName = shift;
3320 return "V8CustomVoidCallback" if $interfaceName eq "VoidCallback";
3321 return "V8$interfaceName";
3324 sub ConvertToV8Parameter
3326 my $signature = shift;
3327 my $nativeType = shift;
3328 my $variableName = shift;
3332 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8Parameter/;
3333 if ($signature->type eq "DOMString") {
3334 $implIncludes{"V8BindingMacros.h"} = 1;
3335 my $macro = "STRING_TO_V8PARAMETER_EXCEPTION_BLOCK";
3336 $macro .= "_$suffix" if $suffix;
3337 return "$macro($nativeType, $variableName, $value);"
3339 # Don't know how to properly check for conversion exceptions when $parameter->type is "DOMUserData"
3340 return "$nativeType $variableName($value, true);";