2009-12-14 Dimitri Glazkov <dglazkov@chromium.org>
[webbrowser.git] / WebCore / bindings / scripts / CodeGeneratorV8.pm
blob9b6349f589cfe4a344b0475872555ab8f6df0a23
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 # aint 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;
28 use File::stat;
29 use Digest::MD5;
31 my $module = "";
32 my $outputDir = "";
34 my @headerContent = ();
35 my @implContentHeader = ();
36 my @implFixedHeader = ();
37 my @implContent = ();
38 my @implContentDecls = ();
39 my %implIncludes = ();
41 my @allParents = ();
43 # Default .h template
44 my $headerTemplate = << "EOF";
46 This file is part of the WebKit open source project.
47 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
49 This library is free software; you can redistribute it and/or
50 modify it under the terms of the GNU Library General Public
51 License as published by the Free Software Foundation; either
52 version 2 of the License, or (at your option) any later version.
54 This library is distributed in the hope that it will be useful,
55 but WITHOUT ANY WARRANTY; without even the implied warranty of
56 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
57 Library General Public License for more details.
59 You should have received a copy of the GNU Library General Public License
60 along with this library; see the file COPYING.LIB. If not, write to
61 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
62 Boston, MA 02111-1307, USA.
64 EOF
66 # Default constructor
67 sub new
69 my $object = shift;
70 my $reference = { };
72 $codeGenerator = shift;
73 $outputDir = shift;
75 bless($reference, $object);
76 return $reference;
79 sub finish
81 my $object = shift;
83 # Commit changes!
84 $object->WriteData();
87 sub leftShift($$) {
88 my ($value, $distance) = @_;
89 return (($value << $distance) & 0xFFFFFFFF);
92 # Workaround for V8 bindings difference where RGBColor is not a POD type.
93 sub IsPodType
95 my $type = shift;
96 return $codeGenerator->IsPodType($type);
99 # Params: 'domClass' struct
100 sub GenerateInterface
102 my $object = shift;
103 my $dataNode = shift;
104 my $defines = shift;
106 # Start actual generation
107 $object->GenerateHeader($dataNode);
108 $object->GenerateImplementation($dataNode);
110 my $name = $dataNode->name;
112 # Open files for writing
113 my $headerFileName = "$outputDir/V8$name.h";
114 my $implFileName = "$outputDir/V8$name.cpp";
116 open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
117 open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
120 # Params: 'idlDocument' struct
121 sub GenerateModule
123 my $object = shift;
124 my $dataNode = shift;
126 $module = $dataNode->module;
129 sub GetLegacyHeaderIncludes
131 my $legacyParent = shift;
133 die "Don't know what headers to include for module $module";
136 sub AvoidInclusionOfType
138 my $type = shift;
140 # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
141 return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
142 return 0;
145 sub UsesManualToJSImplementation
147 my $type = shift;
149 return 1 if $type eq "SVGPathSeg";
150 return 0;
153 sub AddIncludesForType
155 my $type = $codeGenerator->StripModule(shift);
157 # When we're finished with the one-file-per-class
158 # reorganization, we won't need these special cases.
159 if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type)) {
160 } elsif ($type =~ /SVGPathSeg/) {
161 $joinedName = $type;
162 $joinedName =~ s/Abs|Rel//;
163 $implIncludes{"${joinedName}.h"} = 1;
164 } else {
165 # default, include the same named file
166 $implIncludes{GetImplementationFileName(${type})} = 1;
169 # additional includes (things needed to compile the bindings but not the header)
171 if ($type eq "CanvasRenderingContext2D") {
172 $implIncludes{"CanvasGradient.h"} = 1;
173 $implIncludes{"CanvasPattern.h"} = 1;
174 $implIncludes{"CanvasStyle.h"} = 1;
177 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
178 $implIncludes{"PlatformString.h"} = 1;
181 if ($type eq "CSSStyleDeclaration") {
182 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
185 if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
186 # So we can get String -> AtomicString conversion for namedItem().
187 $implIncludes{"AtomicString.h"} = 1;
191 sub AddIncludesForSVGAnimatedType
193 my $type = shift;
194 $type =~ s/SVGAnimated//;
196 if ($type eq "Point" or $type eq "Rect") {
197 $implIncludes{"Float$type.h"} = 1;
198 } elsif ($type eq "String") {
199 $implIncludes{"PlatformString.h"} = 1;
202 $implIncludes{"SVGAnimatedTemplate.h"} = 1;
205 sub AddClassForwardIfNeeded
207 my $implClassName = shift;
209 # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them!
210 push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName);
213 sub GetImplementationFileName
215 my $iface = shift;
216 return "Event.h" if $iface eq "DOMTimeStamp";
217 return "NamedAttrMap.h" if $iface eq "NamedNodeMap";
218 return "NameNodeList.h" if $iface eq "NodeList";
219 return "XMLHttpRequest.h" if $iface eq "XMLHttpRequest";
221 return "${iface}.h";
224 # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if.
225 sub GenerateConditionalString
227 my $node = shift;
228 my $conditional = $node->extendedAttributes->{"Conditional"};
229 if ($conditional) {
230 return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
231 } else {
232 return "";
236 sub GenerateHeader
238 my $object = shift;
239 my $dataNode = shift;
241 my $interfaceName = $dataNode->name;
242 my $className = "V8$interfaceName";
243 my $implClassName = $interfaceName;
245 # Copy contents of parent classes except the first parent or if it is
246 # EventTarget.
247 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
249 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
250 my $conditionalString = GenerateConditionalString($dataNode);
252 # - Add default header template
253 @headerContent = split("\r", $headerTemplate);
255 push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString;
256 push(@headerContent, "\n#ifndef $className" . "_H");
257 push(@headerContent, "\n#define $className" . "_H\n\n");
259 # Get correct pass/store types respecting PODType flag
260 my $podType = $dataNode->extendedAttributes->{"PODType"};
261 my $passType = $podType ? "JSSVGPODTypeWrapper<$podType>*" : "$implClassName*";
263 push(@headerContent, "#include \"$podType.h\"\n") if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
265 push(@headerContent, "#include <v8.h>\n");
266 push(@headerContent, "#include <wtf/HashMap.h>\n");
267 push(@headerContent, "#include \"StringHash.h\"\n");
269 push(@headerContent, "\nnamespace WebCore {\n\n");
270 push(@headerContent, "class V8ClassIndex;\n");
271 push(@headerContent, "\nclass $className {\n");
272 push(@headerContent, <<END);
274 public:
275 static bool HasInstance(v8::Handle<v8::Value> value);
276 static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
279 if ($implClassName eq "DOMWindow") {
280 push(@headerContent, <<END);
281 static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
285 push(@headerContent, <<END);
287 private:
288 static v8::Persistent<v8::FunctionTemplate> GetTemplate();
290 friend class V8ClassIndex;
295 push(@headerContent, "}\n\n");
296 push(@headerContent, "#endif // $className" . "_H\n");
298 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
302 sub GenerateSetDOMException
304 my $indent = shift;
305 my $result = "";
307 $result .= $indent . "if (UNLIKELY(ec)) {\n";
308 $result .= $indent . " V8Proxy::setDOMException(ec);\n";
309 $result .= $indent . " return v8::Handle<v8::Value>();\n";
310 $result .= $indent . "}\n";
312 return $result;
315 sub IsNodeSubType
317 my $dataNode = shift;
318 return 1 if ($dataNode->name eq "Node");
319 foreach (@allParents) {
320 my $parent = $codeGenerator->StripModule($_);
321 return 1 if $parent eq "Node";
323 return 0;
326 sub GetHiddenDependencyIndex
328 my $dataNode = shift;
329 my $attribute = shift;
330 my $name = $dataNode->name;
331 return "V8Custom::kNodeEventListenerCacheIndex" if IsNodeSubType($dataNode);
332 return "V8Custom::kSVGElementInstanceEventListenerCacheIndex" if $name eq "SVGElementInstance";
333 return "V8Custom::kAbstractWorkerRequestCacheIndex" if $name eq "AbstractWorker";
334 return "V8Custom::kWorkerRequestCacheIndex" if $name eq "Worker";
335 return "V8Custom::kDedicatedWorkerContextRequestCacheIndex" if $name eq "DedicatedWorkerContext";
336 return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "WorkerContext";
337 return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "SharedWorkerContext";
338 return "V8Custom::kMessagePortRequestCacheIndex" if $name eq "MessagePort";
339 return "V8Custom::kWebSocketCacheIndex" if $name eq "WebSocket";
340 return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequest";
341 return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequestUpload";
342 return "V8Custom::kDOMApplicationCacheCacheIndex" if $name eq "DOMApplicationCache";
343 return "V8Custom::kNotificationRequestCacheIndex" if $name eq "Notification";
344 return "V8Custom::kDOMWindowEventListenerCacheIndex" if $name eq "DOMWindow";
345 die "Unexpected name " . $name . " when generating " . $attribute;
348 sub HolderToNative
350 my $dataNode = shift;
351 my $implClassName = shift;
352 my $classIndex = shift;
353 my $holder = shift || "holder"; # optional param
355 if (IsNodeSubType($dataNode)) {
356 push(@implContentDecls, <<END);
357 $implClassName* imp = v8DOMWrapperToNode<$implClassName>($holder);
360 } else {
361 push(@implContentDecls, <<END);
362 $implClassName* imp = v8DOMWrapperTo<$implClassName>(V8ClassIndex::$classIndex, $holder);
368 sub GenerateDomainSafeFunctionGetter
370 my $function = shift;
371 my $dataNode = shift;
372 my $classIndex = shift;
373 my $implClassName = shift;
375 my $className = "V8" . $dataNode->name;
376 my $funcName = $function->signature->name;
378 my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
379 if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
380 $signature = "v8::Local<v8::Signature>()";
383 my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature);
385 $implIncludes{"V8Proxy.h"} = 1;
387 push(@implContentDecls, <<END);
388 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
389 INC_STATS(\"DOM.$implClassName.$funcName._get\");
390 static v8::Persistent<v8::FunctionTemplate> private_template =
391 v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
392 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
393 if (holder.IsEmpty()) {
394 // can only reach here by 'object.__proto__.func', and it should passed
395 // domain security check already
397 return private_template->GetFunction();
401 HolderToNative($dataNode, $implClassName, $classIndex);
403 push(@implContentDecls, <<END);
404 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
405 static v8::Persistent<v8::FunctionTemplate> shared_template =
406 v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
407 return shared_template->GetFunction();
409 } else {
410 return private_template->GetFunction();
417 sub GenerateConstructorGetter
419 my $implClassName = shift;
420 my $classIndex = shift;
422 push(@implContentDecls, <<END);
423 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
424 INC_STATS(\"DOM.$implClassName.constructors._get\");
425 v8::Handle<v8::Value> data = info.Data();
426 ASSERT(data->IsNumber());
427 V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(data->Int32Value());
430 if ($classIndex eq "DOMWINDOW") {
431 push(@implContentDecls, <<END);
432 DOMWindow* window = v8DOMWrapperTo<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
433 // Get the proxy corresponding to the DOMWindow if possible to
434 // make sure that the constructor function is constructed in the
435 // context of the DOMWindow and not in the context of the caller.
436 return V8DOMWrapper::getConstructor(type, window);
438 } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") {
439 $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
440 push(@implContentDecls, <<END);
441 WorkerContext* workerContext = v8DOMWrapperTo<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
442 return V8DOMWrapper::getConstructor(type, workerContext);
444 } else {
445 push(@implContentDecls, " return v8::Handle<v8::Value>();");
448 push(@implContentDecls, <<END);
455 sub GenerateNormalAttrGetter
457 my $attribute = shift;
458 my $dataNode = shift;
459 my $classIndex = shift;
460 my $implClassName = shift;
461 my $interfaceName = shift;
463 my $attrExt = $attribute->signature->extendedAttributes;
465 my $attrName = $attribute->signature->name;
466 $implIncludes{"V8Proxy.h"} = 1;
468 my $attrType = GetTypeFromSignature($attribute->signature);
469 my $attrIsPodType = IsPodType($attrType);
471 my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
472 my $isPodType = IsPodType($implClassName);
473 my $skipContext = 0;
476 if ($isPodType) {
477 $implClassName = GetNativeType($implClassName);
478 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
481 # Special case: SVGZoomEvent's attributes are all read-only
482 if ($implClassName eq "SVGZoomEvent") {
483 $attrIsPodType = 0;
484 $skipContext = 1;
487 # Special case: SVGSVGEelement::viewport is read-only
488 if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) {
489 $attrIsPodType = 0;
490 $skipContext = 1;
493 # Special case for SVGColor
494 if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) {
495 $attrIsPodType = 0;
498 my $getterStringUsesImp = $implClassName ne "double";
500 # Getter
501 push(@implContentDecls, <<END);
502 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
503 INC_STATS(\"DOM.$implClassName.$attrName._get\");
506 if ($isPodType) {
507 push(@implContentDecls, <<END);
508 V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());
509 $implClassName imp_instance = *imp_wrapper;
511 if ($getterStringUsesImp) {
512 push(@implContentDecls, <<END);
513 $implClassName* imp = &imp_instance;
517 } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
518 if ($classIndex eq "DOMWINDOW") {
519 push(@implContentDecls, <<END);
520 v8::Handle<v8::Object> holder = info.Holder();
522 } else {
523 # perform lookup first
524 push(@implContentDecls, <<END);
525 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
526 if (holder.IsEmpty()) return v8::Handle<v8::Value>();
529 HolderToNative($dataNode, $implClassName, $classIndex, "info");
530 } else {
531 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
532 if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
533 # Generate super-compact call for regular attribute getter:
534 my $contentAttributeName = $reflect eq "1" ? $attrName : $reflect;
535 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
536 $implIncludes{"${namespace}.h"} = 1;
537 push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
538 push(@implContentDecls, " }\n\n");
539 return;
540 # Skip the rest of the function!
543 push(@implContentDecls, <<END);
544 v8::Handle<v8::Object> holder = info.Holder();
546 HolderToNative($dataNode, $implClassName, $classIndex, "info");
549 # Generate security checks if necessary
550 if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
551 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName())) return v8::Handle<v8::Value>();\n\n");
552 } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
553 push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument())) return v8::Handle<v8::Value>();\n\n");
556 my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType);
557 if ($useExceptions) {
558 $implIncludes{"ExceptionCode.h"} = 1;
559 push(@implContentDecls, " ExceptionCode ec = 0;\n");
562 if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) {
563 $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
566 my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
568 if ($codeGenerator->IsSVGAnimatedType($attribute->signature->type)) {
569 # Some SVGFE*Element.idl use 'operator' as attribute name; rewrite as '_operator' to avoid clashes with C/C++
570 $getterFunc = "_" . $getterFunc if ($attrName =~ /operator/);
571 $getterFunc .= "Animated";
574 my $returnType = GetTypeFromSignature($attribute->signature);
576 my $getterString;
577 if ($getterStringUsesImp) {
578 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
579 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
580 if ($reflect || $reflectURL) {
581 my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
582 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
583 $implIncludes{"${namespace}.h"} = 1;
584 my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
585 $getterString = "imp->$getAttributeFunctionName(${namespace}::${contentAttributeName}Attr";
586 } else {
587 $getterString = "imp->$getterFunc(";
589 $getterString .= "ec" if $useExceptions;
590 $getterString .= ")";
591 if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
592 $getterString .= ".toInt()";
594 } else {
595 $getterString = "imp_instance";
598 my $result;
599 my $wrapper;
601 if ($attrIsPodType) {
602 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
604 my $getter = $getterString;
605 $getter =~ s/imp->//;
606 $getter =~ s/\(\)//;
607 my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
609 my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
610 if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
611 if (IsPodType($implClassName)) {
612 my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)";
613 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
614 } else {
615 my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)";
616 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n");
618 } else {
619 if ($implClassIsAnimatedType) {
620 # We can't hash member function pointers, so instead generate
621 # some hashing material based on the names of the methods.
622 my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8);
623 my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)";
624 push(@implContentDecls, " RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
625 } else {
626 my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString);
627 push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n");
631 } else {
632 if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
633 push(@implContentDecls, " if (!imp->document())\n");
634 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
637 if ($useExceptions) {
638 push(@implContentDecls, " $nativeType v = ");
639 push(@implContentDecls, "$getterString;\n");
640 push(@implContentDecls, GenerateSetDOMException(" "));
641 $result = "v";
642 $result .= ".release()" if (IsRefPtrType($returnType));
643 } else {
644 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
645 $result = $getterString;
649 if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) {
650 if ($attrIsPodType) {
651 push(@implContentDecls, GenerateSVGContextAssignment($implClassName, "wrapper.get()", " "));
652 } else {
653 push(@implContentDecls, GenerateSVGContextRetrieval($implClassName, " "));
654 $result = "V8Proxy::withSVGContext($result, context)";
658 if ($attrIsPodType) {
659 my $classIndex = uc($attrType);
660 push(@implContentDecls, " return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n");
661 } else {
662 push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n");
665 push(@implContentDecls, " }\n\n"); # end of getter
669 sub GenerateReplaceableAttrSetter
671 my $implClassName = shift;
673 $implIncludes{"V8Proxy.h"} = 1;
675 push(@implContentDecls,
676 " static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
677 " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
679 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
681 push(@implContentDecls, " v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n");
682 push(@implContentDecls, " info.Holder()->Delete(${attrName}_string);\n");
683 push(@implContentDecls, " info.This()->Set(${attrName}_string, value);\n");
684 push(@implContentDecls, " }\n\n");
688 sub GenerateNormalAttrSetter
690 my $attribute = shift;
691 my $dataNode = shift;
692 my $classIndex = shift;
693 my $implClassName = shift;
694 my $interfaceName = shift;
696 my $attrExt = $attribute->signature->extendedAttributes;
698 $implIncludes{"V8Proxy.h"} = 1;
700 push(@implContentDecls,
701 " static void ${attrName}AttrSetter(v8::Local<v8::String> name," .
702 " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n");
704 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
706 my $isPodType = IsPodType($implClassName);
708 if ($isPodType) {
709 $implClassName = GetNativeType($implClassName);
710 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
711 push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n");
712 push(@implContentDecls, " $implClassName imp_instance = *wrapper;\n");
713 push(@implContentDecls, " $implClassName* imp = &imp_instance;\n");
715 } elsif ($attrExt->{"v8OnProto"}) {
716 if ($classIndex eq "DOMWINDOW") {
717 push(@implContentDecls, <<END);
718 v8::Handle<v8::Object> holder = info.Holder();
720 } else {
721 # perform lookup first
722 push(@implContentDecls, <<END);
723 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
724 if (holder.IsEmpty()) return;
727 HolderToNative($dataNode, $implClassName, $classIndex, "info");
728 } else {
729 my $attrType = GetTypeFromSignature($attribute->signature);
730 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
731 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
732 if (($reflect || $reflectURL) && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
733 # Generate super-compact call for regular attribute setter:
734 my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
735 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
736 $implIncludes{"${namespace}.h"} = 1;
737 push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
738 push(@implContentDecls, " }\n\n");
739 return;
740 # Skip the rest of the function!
743 push(@implContentDecls, <<END);
744 v8::Handle<v8::Object> holder = info.Holder();
746 HolderToNative($dataNode, $implClassName, $classIndex, "info");
749 my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
750 if ($attribute->signature->type eq "EventListener") {
751 if ($dataNode->name eq "DOMWindow") {
752 push(@implContentDecls, " if (!imp->document())\n");
753 push(@implContentDecls, " return;\n");
755 } else {
756 push(@implContentDecls, " $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
759 my $result = "";
760 if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
761 $result .= "WebCore::String::number(";
763 $result .= "v";
764 if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
765 $result .= ")";
767 my $returnType = GetTypeFromSignature($attribute->signature);
768 if (IsRefPtrType($returnType)) {
769 $result = "WTF::getPtr(" . $result . ")";
772 my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType);
774 if ($useExceptions) {
775 $implIncludes{"ExceptionCode.h"} = 1;
776 push(@implContentDecls, " ExceptionCode ec = 0;\n");
779 if ($implClassName eq "double") {
780 push(@implContentDecls, " *imp = $result;\n");
781 } else {
782 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
783 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
784 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
785 if ($reflect || $reflectURL) {
786 my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
787 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
788 $implIncludes{"${namespace}.h"} = 1;
789 push(@implContentDecls, " imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result");
790 } elsif ($attribute->signature->type eq "EventListener") {
791 $implIncludes{"V8AbstractEventListener.h"} = 1;
792 $implIncludes{"V8CustomBinding.h"} = 1;
793 $cacheIndex = GetHiddenDependencyIndex($dataNode, $attrName);
794 push(@implContentDecls, " transferHiddenDependency(holder, imp->$attrName(), value, $cacheIndex);\n");
795 push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)");
796 } else {
797 push(@implContentDecls, " imp->set$implSetterFunctionName($result");
799 push(@implContentDecls, ", ec") if $useExceptions;
800 push(@implContentDecls, ");\n");
803 if ($useExceptions) {
804 push(@implContentDecls, " if (UNLIKELY(ec))\n");
805 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
808 if ($isPodType) {
809 push(@implContentDecls, " wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
810 } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
811 $implIncludes{"SVGElement.h"} = 1;
813 my $currentObject = "imp";
814 if ($isPodType) {
815 $currentObject = "wrapper";
818 push(@implContentDecls, " if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n");
819 push(@implContentDecls, " context->svgAttributeChanged(imp->associatedAttributeName());\n");
820 push(@implContentDecls, " }\n");
823 push(@implContentDecls, " return;\n");
824 push(@implContentDecls, " }\n\n"); # end of setter
827 sub GetFunctionTemplateCallbackName
829 $function = shift;
830 $dataNode = shift;
832 my $interfaceName = $dataNode->name;
833 my $name = $function->signature->name;
835 if ($function->signature->extendedAttributes->{"Custom"} ||
836 $function->signature->extendedAttributes->{"V8Custom"}) {
837 if ($function->signature->extendedAttributes->{"Custom"} &&
838 $function->signature->extendedAttributes->{"V8Custom"}) {
839 die "Custom and V8Custom should be mutually exclusive!"
841 my $customFunc = $function->signature->extendedAttributes->{"Custom"} ||
842 $function->signature->extendedAttributes->{"V8Custom"};
843 if ($customFunc eq 1) {
844 $customFunc = $interfaceName . $codeGenerator->WK_ucfirst($name);
846 return "V8Custom::v8${customFunc}Callback";
847 } else {
848 return "${interfaceName}Internal::${name}Callback";
852 sub GenerateNewFunctionTemplate
854 $function = shift;
855 $dataNode = shift;
856 $signature = shift;
858 my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
859 return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
862 sub GenerateFunctionCallback
864 my $function = shift;
865 my $dataNode = shift;
866 my $classIndex = shift;
867 my $implClassName = shift;
869 my $interfaceName = $dataNode->name;
870 my $name = $function->signature->name;
872 push(@implContentDecls,
873 " static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" .
874 " INC_STATS(\"DOM.$implClassName.$name\");\n");
876 my $numParameters = @{$function->parameters};
878 if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
879 push(@implContentDecls,
880 " if (args.Length() < $numParameters) return v8::Handle<v8::Value>();\n");
883 if (IsPodType($implClassName)) {
884 my $nativeClassName = GetNativeType($implClassName);
885 push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n");
886 push(@implContentDecls, " $nativeClassName imp_instance = *imp_wrapper;\n");
887 push(@implContentDecls, " $nativeClassName* imp = &imp_instance;\n");
888 } else {
889 push(@implContentDecls, <<END);
890 v8::Handle<v8::Object> holder = args.Holder();
892 HolderToNative($dataNode, $implClassName, $classIndex);
895 # Check domain security if needed
896 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"}
897 || $interfaceName eq "DOMWindow")
898 && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
899 # We have not find real use cases yet.
900 push(@implContentDecls,
901 " if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) {\n".
902 " return v8::Handle<v8::Value>();\n" .
903 " }\n");
906 my $raisesExceptions = @{$function->raisesExceptions};
907 if (!$raisesExceptions) {
908 foreach my $parameter (@{$function->parameters}) {
909 if (TypeCanFailConversion($parameter) or $parameter->extendedAttributes->{"IsIndex"}) {
910 $raisesExceptions = 1;
915 if ($raisesExceptions) {
916 $implIncludes{"ExceptionCode.h"} = 1;
917 push(@implContentDecls, " ExceptionCode ec = 0;\n");
918 push(@implContentDecls, " {\n");
919 # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
920 # of objects (like Strings) declared later, causing compile errors. The block scope ends
921 # right before the label 'fail:'.
924 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
925 push(@implContentDecls,
926 " OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));\n".
927 " if (!callStack)\n".
928 " return v8::Undefined();\n");
929 $implIncludes{"ScriptCallStack.h"} = 1;
931 if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
932 push(@implContentDecls,
933 " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))\n" .
934 " return v8::Handle<v8::Value>();\n");
937 my $paramIndex = 0;
938 foreach my $parameter (@{$function->parameters}) {
939 TranslateParameter($parameter);
941 my $parameterName = $parameter->name;
943 if ($parameter->extendedAttributes->{"Optional"}) {
944 # Generate early call if there are not enough parameters.
945 push(@implContentDecls, " if (args.Length() <= $paramIndex) {\n");
946 my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName);
947 push(@implContentDecls, $functionCall);
948 push(@implContentDecls, " }\n");
951 if (BasicTypeCanFailConversion($parameter)) {
952 push(@implContentDecls, " bool ${parameterName}Ok;\n");
955 push(@implContentDecls, " " . GetNativeTypeFromSignature($parameter, $paramIndex) . " $parameterName = ");
956 push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]",
957 BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n");
959 if (TypeCanFailConversion($parameter)) {
960 $implIncludes{"ExceptionCode.h"} = 1;
961 push(@implContentDecls,
962 " if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" .
963 " ec = TYPE_MISMATCH_ERR;\n" .
964 " goto fail;\n" .
965 " }\n");
968 if ($parameter->extendedAttributes->{"IsIndex"}) {
969 $implIncludes{"ExceptionCode.h"} = 1;
970 push(@implContentDecls,
971 " if (UNLIKELY($parameterName < 0)) {\n" .
972 " ec = INDEX_SIZE_ERR;\n" .
973 " goto fail;\n" .
974 " }\n");
977 $paramIndex++;
980 # Build the function call string.
981 my $callString = GenerateFunctionCallString($function, $paramIndex, " ", $implClassName);
982 push(@implContentDecls, "$callString");
984 if ($raisesExceptions) {
985 push(@implContentDecls, " }\n");
986 push(@implContentDecls, " fail:\n");
987 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
988 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
991 push(@implContentDecls, " }\n\n");
994 sub GenerateBatchedAttributeData
996 my $dataNode = shift;
997 my $interfaceName = $dataNode->name;
998 my $attributes = shift;
1000 foreach my $attribute (@$attributes) {
1001 my $conditionalString = GenerateConditionalString($attribute->signature);
1002 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1003 GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1004 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1008 sub GenerateSingleBatchedAttribute
1010 my $interfaceName = shift;
1011 my $attribute = shift;
1012 my $delimiter = shift;
1013 my $indent = shift;
1014 my $attrName = $attribute->signature->name;
1015 my $attrExt = $attribute->signature->extendedAttributes;
1017 my $accessControl = "v8::DEFAULT";
1018 if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
1019 $accessControl = "v8::ALL_CAN_READ";
1020 } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) {
1021 $accessControl = "v8::ALL_CAN_WRITE";
1022 } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) {
1023 $accessControl = "v8::ALL_CAN_READ";
1024 if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1025 $accessControl .= "|v8::ALL_CAN_WRITE";
1028 if ($attrExt->{"V8DisallowShadowing"}) {
1029 $accessControl .= "|v8::PROHIBITS_OVERWRITING";
1031 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1033 my $customAccessor =
1034 $attrExt->{"Custom"} ||
1035 $attrExt->{"CustomSetter"} ||
1036 $attrExt->{"CustomGetter"} ||
1037 $attrExt->{"V8Custom"} ||
1038 $attrExt->{"V8CustomSetter"} ||
1039 $attrExt->{"V8CustomGetter"} ||
1041 if ($customAccessor eq 1) {
1042 # use the naming convension, interface + (capitalize) attr name
1043 $customAccessor = $interfaceName . $codeGenerator->WK_ucfirst($attrName);
1046 my $getter;
1047 my $setter;
1048 my $propAttr = "v8::None";
1049 my $hasCustomSetter = 0;
1051 # Check attributes.
1052 if ($attrExt->{"DontEnum"}) {
1053 $propAttr .= "|v8::DontEnum";
1055 if ($attrExt->{"V8DisallowShadowing"}) {
1056 $propAttr .= "|v8::DontDelete";
1059 my $on_proto = "0 /* on instance */";
1060 my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */";
1062 # Constructor
1063 if ($attribute->signature->type =~ /Constructor$/) {
1064 my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1065 $constructorType =~ s/Constructor$//;
1066 my $constructorIndex = uc($constructorType);
1067 if ($customAccessor) {
1068 $getter = "V8Custom::v8${customAccessor}AccessorGetter";
1069 } else {
1070 $data = "V8ClassIndex::${constructorIndex}";
1071 $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1073 $setter = "0";
1074 $propAttr = "v8::ReadOnly";
1076 } else {
1077 # Default Getter and Setter
1078 $getter = "${interfaceName}Internal::${attrName}AttrGetter";
1079 $setter = "${interfaceName}Internal::${attrName}AttrSetter";
1081 # Custom Setter
1082 if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1083 $hasCustomSetter = 1;
1084 $setter = "V8Custom::v8${customAccessor}AccessorSetter";
1087 # Custom Getter
1088 if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
1089 $getter = "V8Custom::v8${customAccessor}AccessorGetter";
1093 # Replaceable
1094 if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
1095 $setter = "0";
1096 # Handle the special case of window.top being marked as Replaceable.
1097 # FIXME: Investigate whether we could treat window.top as replaceable
1098 # and allow shadowing without it being a security hole.
1099 if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
1100 $propAttr .= "|v8::ReadOnly";
1104 # Read only attributes
1105 if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
1106 $setter = "0";
1109 # An accessor can be installed on the proto
1110 if ($attrExt->{"v8OnProto"}) {
1111 $on_proto = "1 /* on proto */";
1114 my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
1115 "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1117 push(@implContent, $indent . " {\n");
1118 push(@implContent, $indent . " \/\/ $commentInfo\n");
1119 push(@implContent, $indent . " \"$attrName\",\n");
1120 push(@implContent, $indent . " $getter,\n");
1121 push(@implContent, $indent . " $setter,\n");
1122 push(@implContent, $indent . " $data,\n");
1123 push(@implContent, $indent . " $accessControl,\n");
1124 push(@implContent, $indent . " static_cast<v8::PropertyAttribute>($propAttr),\n");
1125 push(@implContent, $indent . " $on_proto\n");
1126 push(@implContent, $indent . " }" . $delimiter . "\n");
1130 sub GenerateImplementationIndexer
1132 my $dataNode = shift;
1133 my $indexer = shift;
1134 my $interfaceName = $dataNode->name;
1136 if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
1137 $implIncludes{"V8Collection.h"} = 1;
1138 if (!$dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
1139 if ($indexer->type eq "DOMString") {
1140 my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"};
1141 if ($conversion && $conversion eq "Null") {
1142 push(@implContent, <<END);
1143 setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
1145 } else {
1146 push(@implContent, <<END);
1147 setCollectionStringIndexedGetter<${interfaceName}>(desc);
1150 } else {
1151 my $indexerType = $indexer->type;
1152 my $indexerClassIndex = uc($indexerType);
1153 push(@implContent, <<END);
1154 setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc, V8ClassIndex::${indexerClassIndex});
1161 sub GenerateImplementation
1163 my $object = shift;
1164 my $dataNode = shift;
1165 my $interfaceName = $dataNode->name;
1166 my $className = "V8$interfaceName";
1167 my $implClassName = $interfaceName;
1168 my $classIndex = uc($codeGenerator->StripModule($interfaceName));
1170 my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
1171 my $conditionalString = GenerateConditionalString($dataNode);
1173 # - Add default header template
1174 @implContentHeader = split("\r", $headerTemplate);
1176 push(@implFixedHeader,
1177 "#include \"config.h\"\n" .
1178 "#include \"V8Proxy.h\"\n" .
1179 "#include \"V8Binding.h\"\n" .
1180 "#include \"V8BindingState.h\"\n\n" .
1181 "#undef LOG\n\n");
1183 push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
1185 if ($className =~ /^V8SVGAnimated/) {
1186 AddIncludesForSVGAnimatedType($interfaceName);
1189 $implIncludes{"${className}.h"} = 1;
1191 AddIncludesForType($interfaceName);
1192 $implIncludes{"V8Proxy.h"} = 1;
1194 push(@implContentDecls, "namespace WebCore {\n");
1195 push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
1196 push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
1198 my $hasConstructors = 0;
1199 # Generate property accessors for attributes.
1200 for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
1201 $attribute = @{$dataNode->attributes}[$index];
1202 $attrName = $attribute->signature->name;
1203 $attrType = $attribute->signature->type;
1205 # Generate special code for the constructor attributes.
1206 if ($attrType =~ /Constructor$/) {
1207 if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
1208 $implIncludes{"V8CustomBinding.h"} = 1;
1209 } else {
1210 $hasConstructors = 1;
1212 next;
1215 if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
1216 $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
1219 # Do not generate accessor if this is a custom attribute. The
1220 # call will be forwarded to a hand-written accessor
1221 # implementation.
1222 if ($attribute->signature->extendedAttributes->{"Custom"} ||
1223 $attribute->signature->extendedAttributes->{"V8Custom"}) {
1224 $implIncludes{"V8CustomBinding.h"} = 1;
1225 next;
1228 # Generate the accessor.
1229 if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
1230 $implIncludes{"V8CustomBinding.h"} = 1;
1231 } else {
1232 GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName);
1234 if ($attribute->signature->extendedAttributes->{"CustomSetter"} ||
1235 $attribute->signature->extendedAttributes->{"V8CustomSetter"}) {
1236 $implIncludes{"V8CustomBinding.h"} = 1;
1237 } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
1238 $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!";
1239 # GenerateReplaceableAttrSetter($implClassName);
1240 } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
1241 GenerateNormalAttrSetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName);
1245 if ($hasConstructors) {
1246 GenerateConstructorGetter($implClassName, $classIndex);
1249 my $indexer;
1250 # Generate methods for functions.
1251 foreach my $function (@{$dataNode->functions}) {
1252 # hack for addEventListener/RemoveEventListener
1253 # FIXME: avoid naming conflict
1254 if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"}) {
1255 $implIncludes{"V8CustomBinding.h"} = 1;
1256 } else {
1257 GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName);
1260 if ($function->signature->name eq "item") {
1261 $indexer = $function->signature;
1264 # If the function does not need domain security check, we need to
1265 # generate an access getter that returns different function objects
1266 # for different calling context.
1267 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
1268 GenerateDomainSafeFunctionGetter($function, $dataNode, $classIndex, $implClassName);
1272 # Attributes
1273 my $attributes = $dataNode->attributes;
1275 # For the DOMWindow interface we partition the attributes into the
1276 # ones that disallows shadowing and the rest.
1277 my @disallowsShadowing;
1278 # Also separate out attributes that are enabled at runtime so we can process them specially.
1279 my @enabledAtRuntime;
1280 my @normal;
1281 foreach my $attribute (@$attributes) {
1283 if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) {
1284 push(@disallowsShadowing, $attribute);
1285 } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) {
1286 push(@enabledAtRuntime, $attribute);
1287 } else {
1288 push(@normal, $attribute);
1291 $attributes = \@normal;
1292 # Put the attributes that disallow shadowing on the shadow object.
1293 if (@disallowsShadowing) {
1294 push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n");
1295 GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
1296 push(@implContent, "};\n");
1299 my $has_attributes = 0;
1300 if (@$attributes) {
1301 $has_attributes = 1;
1302 push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n");
1303 GenerateBatchedAttributeData($dataNode, $attributes);
1304 push(@implContent, "};\n");
1307 # Setup table of standard callback functions
1308 $num_callbacks = 0;
1309 $has_callbacks = 0;
1310 foreach my $function (@{$dataNode->functions}) {
1311 my $attrExt = $function->signature->extendedAttributes;
1312 # Don't put any nonstandard functions into this table:
1313 if ($attrExt->{"V8OnInstance"}) {
1314 next;
1316 if ($attrExt->{"EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
1317 next;
1319 if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1320 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1321 next;
1323 if ($attrExt->{"DontEnum"} || $attrExt->{"V8ReadOnly"}) {
1324 next;
1326 if (!$has_callbacks) {
1327 $has_callbacks = 1;
1328 push(@implContent, "static const BatchedCallback ${interfaceName}_callbacks[] = {\n");
1330 my $name = $function->signature->name;
1331 my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1332 push(@implContent, <<END);
1333 {"$name", $callback},
1335 $num_callbacks++;
1337 push(@implContent, "};\n") if $has_callbacks;
1339 # Setup constants
1340 my $has_constants = 0;
1341 if (@{$dataNode->constants}) {
1342 $has_constants = 1;
1343 push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n");
1345 foreach my $constant (@{$dataNode->constants}) {
1346 my $name = $constant->name;
1347 my $value = $constant->value;
1348 # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
1349 # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we
1350 # handled this here, and converted it to a -1 constant in the c++ output.
1351 push(@implContent, <<END);
1352 { "${name}", static_cast<signed int>($value) },
1355 if ($has_constants) {
1356 push(@implContent, "};\n");
1359 push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
1361 my $access_check = "";
1362 if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) {
1363 $access_check = "instance->SetAccessCheckCallbacks(V8Custom::v8${interfaceName}NamedSecurityCheck, V8Custom::v8${interfaceName}IndexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));";
1366 # For the DOMWindow interface, generate the shadow object template
1367 # configuration method.
1368 if ($implClassName eq "DOMWindow") {
1369 push(@implContent, <<END);
1370 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) {
1371 batchConfigureAttributes(templ,
1372 v8::Handle<v8::ObjectTemplate>(),
1373 shadow_attrs,
1374 sizeof(shadow_attrs)/sizeof(*shadow_attrs));
1375 return templ;
1380 # find the super descriptor
1381 my $parentClassIndex = "INVALID_CLASS_INDEX";
1382 foreach (@{$dataNode->parents}) {
1383 my $parent = $codeGenerator->StripModule($_);
1384 if ($parent eq "EventTarget") { next; }
1385 $implIncludes{"V8${parent}.h"} = 1;
1386 $parentClassIndex = uc($codeGenerator->StripModule($parent));
1387 last;
1390 # find the field count
1391 my $fieldCount = "V8Custom::kDefaultWrapperInternalFieldCount";
1392 if (IsNodeSubType($dataNode)) {
1393 $fieldCount = "V8Custom::kNodeMinimumInternalFieldCount";
1396 # Generate the template configuration method
1397 push(@implContent, <<END);
1398 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) {
1399 v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\",
1400 V8ClassIndex::$parentClassIndex, $fieldCount,
1403 # Set up our attributes if we have them
1404 if ($has_attributes) {
1405 push(@implContent, <<END);
1406 ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs),
1408 } else {
1409 push(@implContent, <<END);
1410 NULL, 0,
1414 if ($has_callbacks) {
1415 push(@implContent, <<END);
1416 ${interfaceName}_callbacks, sizeof(${interfaceName}_callbacks)/sizeof(*${interfaceName}_callbacks));
1418 } else {
1419 push(@implContent, <<END);
1420 NULL, 0);
1424 if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
1425 push(@implContent, <<END);
1426 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
1427 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
1431 push(@implContent, " $access_check\n");
1433 # Setup the enable-at-runtime attrs if we have them
1434 foreach my $runtime_attr (@enabledAtRuntime) {
1435 $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($runtime_attr->signature->name);
1436 my $conditionalString = GenerateConditionalString($runtime_attr->signature);
1437 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
1438 push(@implContent, " if (V8Custom::v8${enable_function}Enabled()) {\n");
1439 push(@implContent, " static const BatchedAttribute attrData =\\\n");
1440 GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " ");
1441 push(@implContent, <<END);
1442 configureAttribute(instance, proto, attrData);
1445 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1448 GenerateImplementationIndexer($dataNode, $indexer) if $indexer;
1450 # Define our functions with Set() or SetAccessor()
1451 $total_functions = 0;
1452 foreach my $function (@{$dataNode->functions}) {
1453 $total_functions++;
1454 my $attrExt = $function->signature->extendedAttributes;
1455 my $name = $function->signature->name;
1457 my $property_attributes = "v8::DontDelete";
1458 if ($attrExt->{"DontEnum"}) {
1459 $property_attributes .= "|v8::DontEnum";
1461 if ($attrExt->{"V8ReadOnly"}) {
1462 $property_attributes .= "|v8::ReadOnly";
1465 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
1467 my $template = "proto";
1468 if ($attrExt->{"V8OnInstance"}) {
1469 $template = "instance";
1472 my $conditional = "";
1473 if ($attrExt->{"EnabledAtRuntime"}) {
1474 # Only call Set()/SetAccessor() if this method should be enabled
1475 $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($function->signature->name);
1476 $conditional = "if (V8Custom::v8${enable_function}Enabled())\n";
1479 if ($attrExt->{"DoNotCheckDomainSecurity"} &&
1480 ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) {
1481 # Mark the accessor as ReadOnly and set it on the proto object so
1482 # it can be shadowed. This is really a hack to make it work.
1483 # There are several sceneria to call into the accessor:
1484 # 1) from the same domain: "window.open":
1485 # the accessor finds the DOM wrapper in the proto chain;
1486 # 2) from the same domain: "window.__proto__.open":
1487 # the accessor will NOT find a DOM wrapper in the prototype chain
1488 # 3) from another domain: "window.open":
1489 # the access find the DOM wrapper in the prototype chain
1490 # "window.__proto__.open" from another domain will fail when
1491 # accessing '__proto__'
1493 # The solution is very hacky and fragile, it really needs to be replaced
1494 # by a better solution.
1495 $property_attributes .= "|v8::ReadOnly";
1496 push(@implContent, <<END);
1498 // $commentInfo
1499 $conditional $template->SetAccessor(
1500 v8::String::New("$name"),
1501 ${interfaceName}Internal::${name}AttrGetter,
1503 v8::Handle<v8::Value>(),
1504 v8::ALL_CAN_READ,
1505 static_cast<v8::PropertyAttribute>($property_attributes));
1507 $num_callbacks++;
1508 next;
1511 my $signature = "default_signature";
1512 if ($attrExt->{"V8DoNotCheckSignature"}){
1513 $signature = "v8::Local<v8::Signature>()";
1516 if (RequiresCustomSignature($function)) {
1517 $signature = "${name}_signature";
1518 push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function));
1521 # Normal function call is a template
1522 my $callback = GetFunctionTemplateCallbackName($function, $dataNode);
1524 if ($property_attributes eq "v8::DontDelete") {
1525 $property_attributes = "";
1526 } else {
1527 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
1530 if ($template eq "proto" && $conditional eq "" && $signature eq "default_signature" && $property_attributes eq "") {
1531 # Standard type of callback, already created in the batch, so skip it here.
1532 next;
1535 push(@implContent, <<END);
1536 ${conditional}createCallback($template, "$name", $callback, ${signature}$property_attributes);
1538 $num_callbacks++;
1541 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
1543 if ($has_constants) {
1544 push(@implContent, <<END);
1545 batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts));
1549 push(@implContent, <<END);
1550 return desc;
1553 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() {
1554 static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate();
1555 return ${className}_raw_cache_;
1558 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() {
1559 static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate());
1560 return ${className}_cache_;
1563 bool ${className}::HasInstance(v8::Handle<v8::Value> value) {
1564 return GetRawTemplate()->HasInstance(value);
1569 if ($implClassName eq "DOMWindow") {
1570 push(@implContent, <<END);
1571 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() {
1572 static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_;
1573 if (V8DOMWindowShadowObject_cache_.IsEmpty()) {
1574 V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
1575 ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_);
1577 return V8DOMWindowShadowObject_cache_;
1582 push(@implContent, <<END);
1583 } // namespace WebCore
1586 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
1590 sub GenerateFunctionCallString()
1592 my $function = shift;
1593 my $numberOfParameters = shift;
1594 my $indent = shift;
1595 my $implClassName = shift;
1597 my $name = $function->signature->name;
1598 my $isPodType = IsPodType($implClassName);
1599 my $returnType = GetTypeFromSignature($function->signature);
1600 my $returnsPodType = IsPodType($returnType);
1601 my $nativeReturnType = GetNativeType($returnType, 0);
1602 my $result = "";
1604 # Special case: SVG matrix transform methods should not mutate
1605 # the matrix but return a copy
1606 my $copyFirst = 0;
1607 if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") {
1608 $copyFirst = 1;
1611 if ($function->signature->extendedAttributes->{"v8implname"}) {
1612 $name = $function->signature->extendedAttributes->{"v8implname"};
1615 if ($function->signature->extendedAttributes->{"ImplementationFunction"}) {
1616 $name = $function->signature->extendedAttributes->{"ImplementationFunction"};
1619 my $functionString = "imp->${name}(";
1621 if ($copyFirst) {
1622 $functionString = "result.${name}(";
1625 my $returnsListItemPodType = 0;
1626 # SVG lists functions that return POD types require special handling
1627 if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) {
1628 $returnsListItemPodType = 1;
1629 $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n";
1630 $functionString = "listImp->${name}(";
1633 my $first = 1;
1634 my $index = 0;
1635 my $nodeToReturn = 0;
1637 foreach my $parameter (@{$function->parameters}) {
1638 if ($index eq $numberOfParameters) {
1639 last;
1641 if ($first) { $first = 0; }
1642 else { $functionString .= ", "; }
1643 my $paramName = $parameter->name;
1644 my $paramType = $parameter->type;
1646 # This is a bit of a hack... we need to convert parameters to methods on SVG lists
1647 # of POD types which are items in the list to appropriate SVGList<> instances
1648 if ($returnsListItemPodType && $paramType . "List" eq $implClassName) {
1649 $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
1652 if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
1653 $functionString .= "$paramName.get()";
1654 } else {
1655 $functionString .= $paramName;
1658 if ($parameter->extendedAttributes->{"Return"}) {
1659 $nodeToReturn = $parameter->name;
1661 $index++;
1664 if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
1665 $functionString .= ", " if not $first;
1666 $functionString .= "callStack.get()";
1667 if ($first) { $first = 0; }
1670 if (@{$function->raisesExceptions}) {
1671 $functionString .= ", " if not $first;
1672 $functionString .= "ec";
1674 $functionString .= ")";
1676 my $return = "result";
1677 my $returnIsRef = IsRefPtrType($returnType);
1679 if ($nodeToReturn) {
1680 # Special case for insertBefore, replaceChild, removeChild and
1681 # appendChild functions from Node.
1682 $result .= $indent . "bool success = $functionString;\n";
1683 if (@{$function->raisesExceptions}) {
1684 $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
1686 $result .= $indent . "if (success)\n";
1687 $result .= $indent . " " .
1688 "return V8DOMWrapper::convertNodeToV8Object($nodeToReturn);\n";
1689 $result .= $indent . "return v8::Null();\n";
1690 return $result;
1691 } elsif ($returnType eq "void") {
1692 $result .= $indent . "$functionString;\n";
1693 } elsif ($copyFirst) {
1694 $result .=
1695 $indent . GetNativeType($returnType, 0) . " result = *imp;\n" .
1696 $indent . "$functionString;\n";
1697 } elsif ($returnsListItemPodType) {
1698 $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n";
1699 } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) {
1700 $result .= $indent . $nativeReturnType . " result = $functionString;\n";
1701 } else {
1702 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
1703 $return = $functionString;
1704 $returnIsRef = 0;
1707 if (@{$function->raisesExceptions}) {
1708 $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n";
1711 # If the return type is a POD type, separate out the wrapper generation
1712 if ($returnsListItemPodType) {
1713 $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1714 $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n";
1715 $return = "wrapper";
1716 } elsif ($returnsPodType) {
1717 $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = ";
1718 $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
1719 $return = "wrapper";
1722 my $generatedSVGContextRetrieval = 0;
1723 # If the return type needs an SVG context, output it
1724 if (IsSVGTypeNeedingContextParameter($returnType)) {
1725 $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent);
1726 $generatedSVGContextRetrieval = 1;
1729 if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) {
1730 if (!$generatedSVGContextRetrieval) {
1731 $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1732 $generatedSVGContextRetrieval = 1;
1735 $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n";
1736 $implIncludes{"SVGElement.h"} = 1;
1739 # If the implementing class is a POD type, commit changes
1740 if ($isPodType) {
1741 if (!$generatedSVGContextRetrieval) {
1742 $result .= GenerateSVGContextRetrieval($implClassName, $indent);
1743 $generatedSVGContextRetrieval = 1;
1746 $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n";
1749 if ($returnsPodType) {
1750 my $classIndex = uc($returnType);
1751 $result .= $indent . "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n";
1752 } else {
1753 $return .= ".release()" if ($returnIsRef);
1754 $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n";
1757 return $result;
1761 sub GetTypeFromSignature
1763 my $signature = shift;
1765 return $codeGenerator->StripModule($signature->type);
1769 sub GetNativeTypeFromSignature
1771 my $signature = shift;
1772 my $parameterIndex = shift;
1774 my $type = GetTypeFromSignature($signature);
1776 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
1777 # Special-case index arguments because we need to check that they aren't < 0.
1778 return "int";
1781 $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
1783 if ($parameterIndex >= 0 && $type eq "V8Parameter") {
1784 my $mode = "";
1785 if ($signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}) {
1786 $mode = "WithUndefinedOrNullCheck";
1787 } elsif ($signature->extendedAttributes->{"ConvertNullToNullString"}) {
1788 $mode = "WithNullCheck";
1790 $type .= "<$mode>";
1793 return $type;
1796 sub IsRefPtrType
1798 my $type = shift;
1799 return 1 if $type eq "Attr";
1800 return 1 if $type eq "CanvasBooleanArray";
1801 return 1 if $type eq "CanvasGradient";
1802 return 1 if $type eq "CanvasObject";
1803 return 1 if $type eq "ClientRect";
1804 return 1 if $type eq "ClientRectList";
1805 return 1 if $type eq "CDATASection";
1806 return 1 if $type eq "Comment";
1807 return 1 if $type eq "CSSRule";
1808 return 1 if $type eq "CSSStyleRule";
1809 return 1 if $type eq "CSSCharsetRule";
1810 return 1 if $type eq "CSSImportRule";
1811 return 1 if $type eq "CSSMediaRule";
1812 return 1 if $type eq "CSSFontFaceRule";
1813 return 1 if $type eq "CSSPageRule";
1814 return 1 if $type eq "CSSPrimitiveValue";
1815 return 1 if $type eq "CSSStyleSheet";
1816 return 1 if $type eq "CSSStyleDeclaration";
1817 return 1 if $type eq "CSSValue";
1818 return 1 if $type eq "CSSRuleList";
1819 return 1 if $type eq "Database";
1820 return 1 if $type eq "Document";
1821 return 1 if $type eq "DocumentFragment";
1822 return 1 if $type eq "DocumentType";
1823 return 1 if $type eq "Element";
1824 return 1 if $type eq "EntityReference";
1825 return 1 if $type eq "Event";
1826 return 1 if $type eq "EventListener";
1827 return 1 if $type eq "FileList";
1828 return 1 if $type eq "HTMLCollection";
1829 return 1 if $type eq "HTMLAllCollection";
1830 return 1 if $type eq "HTMLDocument";
1831 return 1 if $type eq "HTMLElement";
1832 return 1 if $type eq "HTMLOptionsCollection";
1833 return 1 if $type eq "ImageData";
1834 return 1 if $type eq "Media";
1835 return 1 if $type eq "MediaError";
1836 return 1 if $type eq "MimeType";
1837 return 1 if $type eq "Node";
1838 return 1 if $type eq "NodeList";
1839 return 1 if $type eq "NodeFilter";
1840 return 1 if $type eq "NodeIterator";
1841 return 1 if $type eq "NSResolver";
1842 return 1 if $type eq "Plugin";
1843 return 1 if $type eq "ProcessingInstruction";
1844 return 1 if $type eq "Range";
1845 return 1 if $type eq "RGBColor";
1846 return 1 if $type eq "Text";
1847 return 1 if $type eq "TextMetrics";
1848 return 1 if $type eq "TimeRanges";
1849 return 1 if $type eq "TreeWalker";
1850 return 1 if $type eq "WebGLActiveInfo";
1851 return 1 if $type eq "WebGLArray";
1852 return 1 if $type eq "WebGLArrayBuffer";
1853 return 1 if $type eq "WebGLByteArray";
1854 return 1 if $type eq "WebGLBuffer";
1855 return 1 if $type eq "WebGLFloatArray";
1856 return 1 if $type eq "WebGLFramebuffer";
1857 return 1 if $type eq "WebGLIntArray";
1858 return 1 if $type eq "WebGLProgram";
1859 return 1 if $type eq "WebGLRenderbuffer";
1860 return 1 if $type eq "WebGLShader";
1861 return 1 if $type eq "WebGLShortArray";
1862 return 1 if $type eq "WebGLTexture";
1863 return 1 if $type eq "WebGLUniformLocation";
1864 return 1 if $type eq "WebGLUnsignedByteArray";
1865 return 1 if $type eq "WebGLUnsignedIntArray";
1866 return 1 if $type eq "WebGLUnsignedShortArray";
1867 return 1 if $type eq "WebKitCSSMatrix";
1868 return 1 if $type eq "WebKitPoint";
1869 return 1 if $type eq "XPathExpression";
1870 return 1 if $type eq "XPathNSResolver";
1871 return 1 if $type eq "XPathResult";
1873 return 1 if $type eq "SVGAngle";
1874 return 1 if $type eq "SVGElementInstance";
1875 return 1 if $type eq "SVGElementInstanceList";
1876 return 1 if $type =~ /^SVGPathSeg/;
1878 return 1 if $type =~ /^SVGAnimated/;
1880 return 0;
1883 sub IsVideoClassName
1885 my $class = shift;
1886 return 1 if $class eq "V8HTMLAudioElement";
1887 return 1 if $class eq "V8HTMLMediaElement";
1888 return 1 if $class eq "V8HTMLSourceElement";
1889 return 1 if $class eq "V8HTMLVideoElement";
1890 return 1 if $class eq "V8MediaError";
1891 return 1 if $class eq "V8TimeRanges";
1893 return 0;
1896 sub IsWorkerClassName
1898 my $class = shift;
1899 return 1 if $class eq "V8Worker";
1900 return 1 if $class eq "V8WorkerContext";
1901 return 1 if $class eq "V8WorkerLocation";
1902 return 1 if $class eq "V8WorkerNavigator";
1904 return 0;
1907 sub GetNativeType
1909 my $type = shift;
1910 my $isParameter = shift;
1912 if ($type eq "float" or $type eq "double") {
1913 return $type;
1916 return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
1917 return "int" if $type eq "int";
1918 return "int" if $type eq "short" or $type eq "unsigned short";
1919 return "unsigned" if $type eq "unsigned long";
1920 return "int" if $type eq "long";
1921 return "unsigned long long" if $type eq "unsigned long long";
1922 return "bool" if $type eq "boolean";
1923 return "String" if $type eq "DOMString";
1924 return "Range::CompareHow" if $type eq "CompareHow";
1925 return "FloatRect" if $type eq "SVGRect";
1926 return "FloatPoint" if $type eq "SVGPoint";
1927 return "TransformationMatrix" if $type eq "SVGMatrix";
1928 return "SVGTransform" if $type eq "SVGTransform";
1929 return "SVGLength" if $type eq "SVGLength";
1930 return "double" if $type eq "SVGNumber";
1931 return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
1932 return "DOMTimeStamp" if $type eq "DOMTimeStamp";
1933 return "unsigned" if $type eq "unsigned int";
1934 return "Node*" if $type eq "EventTarget" and $isParameter;
1936 return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack?
1938 # temporary hack
1939 return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
1941 # necessary as resolvers could be constructed on fly.
1942 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
1944 return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
1946 # Default, assume native type is a pointer with same type name as idl type
1947 return "${type}*";
1951 my %typeCanFailConversion = (
1952 "Attr" => 1,
1953 "WebGLArray" => 0,
1954 "WebGLBuffer" => 0,
1955 "WebGLByteArray" => 0,
1956 "WebGLFloatArray" => 0,
1957 "WebGLFramebuffer" => 0,
1958 "CanvasGradient" => 0,
1959 "WebGLIntArray" => 0,
1960 "CanvasPixelArray" => 0,
1961 "WebGLProgram" => 0,
1962 "WebGLRenderbuffer" => 0,
1963 "WebGLShader" => 0,
1964 "WebGLShortArray" => 0,
1965 "WebGLTexture" => 0,
1966 "WebGLUniformLocation" => 0,
1967 "CompareHow" => 0,
1968 "DataGridColumn" => 0,
1969 "DOMString" => 0,
1970 "DOMWindow" => 0,
1971 "DocumentType" => 0,
1972 "Element" => 0,
1973 "Event" => 0,
1974 "EventListener" => 0,
1975 "EventTarget" => 0,
1976 "HTMLCanvasElement" => 0,
1977 "HTMLElement" => 0,
1978 "HTMLImageElement" => 0,
1979 "HTMLOptionElement" => 0,
1980 "HTMLVideoElement" => 0,
1981 "Node" => 0,
1982 "NodeFilter" => 0,
1983 "MessagePort" => 0,
1984 "NSResolver" => 0,
1985 "Range" => 0,
1986 "SQLResultSet" => 0,
1987 "Storage" => 0,
1988 "SVGAngle" => 0,
1989 "SVGElement" => 0,
1990 "SVGLength" => 1,
1991 "SVGMatrix" => 1,
1992 "SVGNumber" => 0,
1993 "SVGPaintType" => 0,
1994 "SVGPathSeg" => 0,
1995 "SVGPoint" => 1,
1996 "SVGRect" => 1,
1997 "SVGTransform" => 1,
1998 "VoidCallback" => 1,
1999 "WebKitCSSMatrix" => 0,
2000 "WebKitPoint" => 0,
2001 "XPathEvaluator" => 0,
2002 "XPathNSResolver" => 0,
2003 "XPathResult" => 0,
2004 "boolean" => 0,
2005 "double" => 0,
2006 "float" => 0,
2007 "long" => 0,
2008 "unsigned long" => 0,
2009 "unsigned short" => 0,
2013 sub TranslateParameter
2015 my $signature = shift;
2017 # The IDL uses some pseudo-types which don't really exist.
2018 if ($signature->type eq "TimeoutHandler") {
2019 $signature->type("DOMString");
2023 sub BasicTypeCanFailConversion
2025 my $signature = shift;
2026 my $type = GetTypeFromSignature($signature);
2028 return 1 if $type eq "SVGLength";
2029 return 1 if $type eq "SVGMatrix";
2030 return 1 if $type eq "SVGPoint";
2031 return 1 if $type eq "SVGRect";
2032 return 1 if $type eq "SVGTransform";
2033 return 0;
2036 sub TypeCanFailConversion
2038 my $signature = shift;
2040 my $type = GetTypeFromSignature($signature);
2042 $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr";
2044 return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type};
2046 die "Don't know whether a JS value can fail conversion to type $type.";
2049 sub JSValueToNative
2051 my $signature = shift;
2052 my $value = shift;
2053 my $okParam = shift;
2054 my $maybeOkParam = $okParam ? ", ${okParam}" : "";
2056 my $type = GetTypeFromSignature($signature);
2058 return "$value" if $type eq "JSObject";
2059 return "$value->BooleanValue()" if $type eq "boolean";
2060 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
2061 return "$value->NumberValue()" if $type eq "SVGNumber";
2063 return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long";
2064 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
2065 return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
2067 if ($type eq "DOMString" or $type eq "DOMUserData") {
2068 return $value;
2071 if ($type eq "SerializedScriptValue") {
2072 $implIncludes{"SerializedScriptValue.h"} = 1;
2073 return "SerializedScriptValue::create($value)";
2076 if ($type eq "NodeFilter") {
2077 return "V8DOMWrapper::wrapNativeNodeFilter($value)";
2080 if ($type eq "SVGRect") {
2081 $implIncludes{"FloatRect.h"} = 1;
2084 if ($type eq "SVGPoint") {
2085 $implIncludes{"FloatPoint.h"} = 1;
2088 # Default, assume autogenerated type conversion routines
2089 $implIncludes{"V8Proxy.h"} = 1;
2090 if ($type eq "EventTarget") {
2091 $implIncludes{"V8Node.h"} = 1;
2093 # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
2094 return "V8Node::HasInstance($value) ? v8DOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0";
2097 if ($type eq "XPathNSResolver") {
2098 return "V8DOMWrapper::getXPathNSResolver($value)";
2101 AddIncludesForType($type);
2102 # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type);
2104 if (IsDOMNodeType($type)) {
2105 $implIncludes{"V8${type}.h"} = 1;
2107 # Perform type checks on the parameter, if it is expected Node type,
2108 # return NULL.
2109 return "V8${type}::HasInstance($value) ? v8DOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0";
2110 } else {
2111 # TODO: Temporary to avoid Window name conflict.
2112 my $classIndex = uc($type);
2113 my $implClassName = ${type};
2115 $implIncludes{"V8$type.h"} = 1;
2117 if (IsPodType($type)) {
2118 my $nativeType = GetNativeType($type);
2119 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2121 return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})"
2124 $implIncludes{"V8${type}.h"} = 1;
2126 # Perform type checks on the parameter, if it is expected Node type,
2127 # return NULL.
2128 return "V8${type}::HasInstance($value) ? v8DOMWrapperTo<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0";
2133 sub GetV8HeaderName
2135 my $type = shift;
2136 return "V8" . GetImplementationFileName($type);
2140 sub CreateCustomSignature
2142 my $function = shift;
2143 my $count = @{$function->parameters};
2144 my $name = $function->signature->name;
2145 my $result = " const int ${name}_argc = ${count};\n" .
2146 " v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { ";
2147 my $first = 1;
2148 foreach my $parameter (@{$function->parameters}) {
2149 if ($first) { $first = 0; }
2150 else { $result .= ", "; }
2151 if (IsWrapperType($parameter->type)) {
2152 if ($parameter->type eq "XPathNSResolver") {
2153 # Special case for XPathNSResolver. All other browsers accepts a callable,
2154 # so, even though it's against IDL, accept objects here.
2155 $result .= "v8::Handle<v8::FunctionTemplate>()";
2156 } else {
2157 my $type = $parameter->type;
2158 my $header = GetV8HeaderName($type);
2159 $implIncludes{$header} = 1;
2160 $result .= "V8${type}::GetRawTemplate()";
2162 } else {
2163 $result .= "v8::Handle<v8::FunctionTemplate>()";
2166 $result .= " };\n";
2167 $result .= " v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n";
2168 return $result;
2172 sub RequiresCustomSignature
2174 my $function = shift;
2175 # No signature needed for Custom function
2176 if ($function->signature->extendedAttributes->{"Custom"} ||
2177 $function->signature->extendedAttributes->{"V8Custom"}) {
2178 return 0;
2181 foreach my $parameter (@{$function->parameters}) {
2182 if (IsWrapperType($parameter->type)) {
2183 return 1;
2186 return 0;
2190 my %non_wrapper_types = (
2191 'float' => 1,
2192 'double' => 1,
2193 'short' => 1,
2194 'unsigned short' => 1,
2195 'long' => 1,
2196 'unsigned long' => 1,
2197 'boolean' => 1,
2198 'DOMString' => 1,
2199 'CompareHow' => 1,
2200 'SVGRect' => 1,
2201 'SVGPoint' => 1,
2202 'SVGMatrix' => 1,
2203 'SVGTransform' => 1,
2204 'SVGLength' => 1,
2205 'SVGNumber' => 1,
2206 'SVGPaintType' => 1,
2207 'DOMTimeStamp' => 1,
2208 'JSObject' => 1,
2209 'EventTarget' => 1,
2210 'NodeFilter' => 1,
2211 'EventListener' => 1
2215 sub IsWrapperType
2217 my $type = $codeGenerator->StripModule(shift);
2218 return !($non_wrapper_types{$type});
2221 sub IsDOMNodeType
2223 my $type = shift;
2225 return 1 if $type eq 'Attr';
2226 return 1 if $type eq 'CDATASection';
2227 return 1 if $type eq 'Comment';
2228 return 1 if $type eq 'Document';
2229 return 1 if $type eq 'DocumentFragment';
2230 return 1 if $type eq 'DocumentType';
2231 return 1 if $type eq 'Element';
2232 return 1 if $type eq 'EntityReference';
2233 return 1 if $type eq 'HTMLCanvasElement';
2234 return 1 if $type eq 'HTMLDocument';
2235 return 1 if $type eq 'HTMLElement';
2236 return 1 if $type eq 'HTMLFormElement';
2237 return 1 if $type eq 'HTMLTableCaptionElement';
2238 return 1 if $type eq 'HTMLTableSectionElement';
2239 return 1 if $type eq 'Node';
2240 return 1 if $type eq 'ProcessingInstruction';
2241 return 1 if $type eq 'SVGElement';
2242 return 1 if $type eq 'SVGDocument';
2243 return 1 if $type eq 'SVGSVGElement';
2244 return 1 if $type eq 'SVGUseElement';
2245 return 1 if $type eq 'Text';
2247 return 0;
2251 sub ReturnNativeToJSValue
2253 my $signature = shift;
2254 my $value = shift;
2255 my $indent = shift;
2256 my $type = GetTypeFromSignature($signature);
2257 my $className= "V8$type";
2259 return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
2260 return "return v8Boolean($value)" if $type eq "boolean";
2261 return "return v8::Handle<v8::Value>()" if $type eq "void"; # equivalent to v8::Undefined()
2263 # For all the types where we use 'int' as the representation type,
2264 # we use Integer::New which has a fast Smi conversion check.
2265 my $nativeType = GetNativeType($type);
2266 return "return v8::Integer::New($value)" if $nativeType eq "int";
2267 return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
2269 return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType";
2271 if ($codeGenerator->IsStringType($type)) {
2272 my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
2273 if (defined $conv) {
2274 return "return v8StringOrNull($value)" if $conv eq "Null";
2275 return "return v8StringOrUndefined($value)" if $conv eq "Undefined";
2276 return "return v8StringOrFalse($value)" if $conv eq "False";
2278 die "Unknown value for ConvertNullStringTo extended attribute";
2280 return "return v8String($value)";
2283 # V8 specific.
2284 my $implClassName = $type;
2285 AddIncludesForType($type);
2286 # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type);
2288 # special case for non-DOM node interfaces
2289 if (IsDOMNodeType($type)) {
2290 if ($signature->extendedAttributes->{"ReturnsNew"}) {
2291 return "return V8DOMWrapper::convertNewNodeToV8Object($value)";
2292 } else {
2293 return "return V8DOMWrapper::convertNodeToV8Object($value)";
2297 if ($type eq "EventTarget" or $type eq "SVGElementInstance") {
2298 return "return V8DOMWrapper::convertEventTargetToV8Object($value)";
2301 if ($type eq "Event") {
2302 return "return V8DOMWrapper::convertEventToV8Object($value)";
2305 if ($type eq "EventListener") {
2306 return "return V8DOMWrapper::convertEventListenerToV8Object(imp->scriptExecutionContext(), $value)";
2309 if ($type eq "SerializedScriptValue") {
2310 $implIncludes{"$type.h"} = 1;
2311 return "return v8String($value->toString())";
2314 if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") {
2315 $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2316 return "return WorkerContextExecutionProxy::convertWorkerContextToV8Object($value)";
2319 if ($type eq "WorkerLocation" or $type eq "WorkerNavigator" or $type eq "NotificationCenter") {
2320 $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
2321 my $classIndex = uc($type);
2323 return "return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2326 else {
2327 $implIncludes{"wtf/RefCounted.h"} = 1;
2328 $implIncludes{"wtf/RefPtr.h"} = 1;
2329 $implIncludes{"wtf/GetPtr.h"} = 1;
2330 my $classIndex = uc($type);
2332 if (IsPodType($type)) {
2333 $value = GenerateSVGStaticPodTypeWrapper($type, $value);
2336 return "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, $value)";
2340 sub GenerateSVGStaticPodTypeWrapper {
2341 my $type = shift;
2342 my $value = shift;
2344 $implIncludes{"V8$type.h"}=1;
2345 $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
2347 my $nativeType = GetNativeType($type);
2348 return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)";
2351 # Internal helper
2352 sub WriteData
2354 if (defined($IMPL)) {
2355 # Write content to file.
2356 print $IMPL @implContentHeader;
2358 print $IMPL @implFixedHeader;
2360 foreach my $implInclude (sort keys(%implIncludes)) {
2361 my $checkType = $implInclude;
2362 $checkType =~ s/\.h//;
2364 print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
2367 print $IMPL "\n";
2368 print $IMPL @implContentDecls;
2369 print $IMPL @implContent;
2370 close($IMPL);
2371 undef($IMPL);
2373 %implIncludes = ();
2374 @implFixedHeader = ();
2375 @implHeaderContent = ();
2376 @implContentDecls = ();
2377 @implContent = ();
2380 if (defined($HEADER)) {
2381 # Write content to file.
2382 print $HEADER @headerContent;
2383 close($HEADER);
2384 undef($HEADER);
2386 @headerContent = ();
2390 sub IsSVGTypeNeedingContextParameter
2392 my $implClassName = shift;
2394 if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
2395 return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
2398 return 0;
2401 sub GenerateSVGContextAssignment
2403 my $srcType = shift;
2404 my $value = shift;
2405 my $indent = shift;
2407 $result = GenerateSVGContextRetrieval($srcType, $indent);
2408 $result .= $indent . "V8Proxy::setSVGContext($value, context);\n";
2410 return $result;
2413 sub GenerateSVGContextRetrieval
2415 my $srcType = shift;
2416 my $indent = shift;
2418 my $srcIsPodType = IsPodType($srcType);
2420 my $srcObject = "imp";
2421 if ($srcIsPodType) {
2422 $srcObject = "imp_wrapper";
2425 my $contextDecl;
2427 if (IsSVGTypeNeedingContextParameter($srcType)) {
2428 $contextDecl = "V8Proxy::svgContext($srcObject)";
2429 } else {
2430 $contextDecl = $srcObject;
2433 return $indent . "SVGElement* context = $contextDecl;\n";
2436 sub IsSVGListMutator
2438 my $functionName = shift;
2440 return 1 if $functionName eq "clear";
2441 return 1 if $functionName eq "initialize";
2442 return 1 if $functionName eq "insertItemBefore";
2443 return 1 if $functionName eq "replaceItem";
2444 return 1 if $functionName eq "removeItem";
2445 return 1 if $functionName eq "appendItem";
2447 return 0;
2450 sub IsSVGListMethod
2452 my $functionName = shift;
2454 return 1 if $functionName eq "getFirst";
2455 return 1 if $functionName eq "getLast";
2456 return 1 if $functionName eq "getItem";
2458 return IsSVGListMutator($functionName);
2461 sub IsSVGListTypeNeedingSpecialHandling
2463 my $className = shift;
2465 return 1 if $className eq "SVGPointList";
2466 return 1 if $className eq "SVGTransformList";
2468 return 0;
2471 sub DebugPrint
2473 my $output = shift;
2475 print $output;
2476 print "\n";