1 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
2 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
3 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
4 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
5 # Copyright (C) 2006 Apple Computer, Inc.
6 # Copyright (C) 2007, 2008, 2009, 2012 Google Inc.
7 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
8 # Copyright (C) Research In Motion Limited 2010. All rights reserved.
9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
11 # This library is free software; you can redistribute it and/or
12 # modify it under the terms of the GNU Library General Public
13 # License as published by the Free Software Foundation; either
14 # version 2 of the License, or (at your option) any later version.
16 # This library is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 # Library General Public License for more details.
21 # You should have received a copy of the GNU Library General Public License
22 # along with this library; see the file COPYING.LIB. If not, write to
23 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 # Boston, MA 02111-1307, USA.
27 package CodeGeneratorV8;
33 use constant FileNamePrefix => "V8";
39 my $outputHeadersDir = "";
41 my @headerContent = ();
42 my @implContentHeader = ();
43 my @implFixedHeader = ();
45 my @implContentDecls = ();
46 my %implIncludes = ();
47 my %headerIncludes = ();
52 my $headerTemplate = << "EOF";
54 This file is part of the WebKit open source project.
55 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
57 This library is free software; you can redistribute it and/or
58 modify it under the terms of the GNU Library General Public
59 License as published by the Free Software Foundation; either
60 version 2 of the License, or (at your option) any later version.
62 This library is distributed in the hope that it will be useful,
63 but WITHOUT ANY WARRANTY; without even the implied warranty of
64 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
65 Library General Public License for more details.
67 You should have received a copy of the GNU Library General Public License
68 along with this library; see the file COPYING.LIB. If not, write to
69 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
70 Boston, MA 02111-1307, USA.
80 $codeGenerator = shift;
82 $outputHeadersDir = shift;
84 bless($reference, $object);
88 # Params: 'domClass' struct
95 # Start actual generation
96 if ($dataNode->extendedAttributes->{"Callback"}) {
97 $object->GenerateCallbackHeader($dataNode);
98 $object->GenerateCallbackImplementation($dataNode);
100 $object->GenerateHeader($dataNode);
101 $object->GenerateImplementation($dataNode);
104 $object->WriteData($dataNode);
107 # Params: 'idlDocument' struct
111 my $dataNode = shift;
113 $module = $dataNode->module;
116 sub AddToImplIncludes
119 my $conditional = shift;
121 if (not $conditional) {
122 $implIncludes{$header} = 1;
123 } elsif (not exists($implIncludes{$header})) {
124 $implIncludes{$header} = $conditional;
126 my $oldValue = $implIncludes{$header};
127 if ($oldValue ne 1) {
129 $newValue{$conditional} = 1;
130 foreach my $condition (split(/\|/, $oldValue)) {
131 $newValue{$condition} = 1;
133 $implIncludes{$header} = join("|", sort keys %newValue);
138 sub AddIncludesForType
140 my $type = $codeGenerator->StripModule(shift);
142 # When we're finished with the one-file-per-class
143 # reorganization, we won't need these special cases.
144 if (IsTypedArrayType($type)) {
145 AddToImplIncludes("wtf/${type}.h");
147 if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->IsStringType($type) and !$codeGenerator->AvoidInclusionOfType($type) and $type ne "Date") {
148 # default, include the same named file
149 AddToImplIncludes(GetV8HeaderName(${type}));
151 if ($type =~ /SVGPathSeg/) {
152 my $joinedName = $type;
153 $joinedName =~ s/Abs|Rel//;
154 AddToImplIncludes("${joinedName}.h");
158 # additional includes (things needed to compile the bindings but not the header)
160 if ($type eq "CanvasRenderingContext2D") {
161 AddToImplIncludes("CanvasGradient.h");
162 AddToImplIncludes("CanvasPattern.h");
163 AddToImplIncludes("CanvasStyle.h");
166 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
167 AddToImplIncludes("PlatformString.h");
170 if ($type eq "CSSStyleSheet" or $type eq "StyleSheet") {
171 AddToImplIncludes("CSSImportRule.h");
174 if ($type eq "CSSStyleDeclaration") {
175 AddToImplIncludes("StylePropertySet.h");
178 if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
179 # So we can get String -> AtomicString conversion for namedItem().
180 AddToImplIncludes("wtf/text/AtomicString.h");
184 sub GenerateConditionalString
187 my $conditional = $node->extendedAttributes->{"Conditional"};
189 return $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
195 sub GetSVGPropertyTypes
197 my $implType = shift;
200 my $svgListPropertyType;
203 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
205 $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
206 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
208 # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType>
209 $svgNativeType = "$svgNativeType ";
211 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
212 if ($svgNativeType =~ /SVGPropertyTearOff/) {
213 $svgPropertyType = $svgWrappedNativeType;
214 AddToImplIncludes("SVGAnimatedPropertyTearOff.h");
215 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
216 $svgListPropertyType = $svgWrappedNativeType;
217 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
218 $headerIncludes{"SVGStaticListPropertyTearOff.h"} = 1;
219 } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
220 $svgListPropertyType = $svgWrappedNativeType;
221 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
222 $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
223 } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
224 $svgListPropertyType = $svgWrappedNativeType;
225 $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
228 if ($svgPropertyType) {
229 $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint";
232 return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
238 my $dataNode = shift;
240 my $interfaceName = $dataNode->name;
241 my $className = "V8$interfaceName";
242 my $implClassName = $interfaceName;
244 # Copy contents of parent classes except the first parent or if it is
246 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
247 $codeGenerator->LinkOverloadedFunctions($dataNode);
249 my $hasDependentLifetime = $dataNode->extendedAttributes->{"V8DependentLifetime"} || $dataNode->extendedAttributes->{"ActiveDOMObject"} || $className =~ /SVG/;
250 if (!$hasDependentLifetime) {
251 foreach (@{$dataNode->parents}) {
252 my $parent = $codeGenerator->StripModule($_);
253 next if $parent eq "EventTarget";
254 $headerIncludes{"V8${parent}.h"} = 1;
258 # - Add default header template
259 push(@headerContent, GenerateHeaderContentHeader($dataNode));
261 $headerIncludes{"wtf/text/StringHash.h"} = 1;
262 $headerIncludes{"WrapperTypeInfo.h"} = 1;
263 $headerIncludes{"V8DOMWrapper.h"} = 1;
264 $headerIncludes{"wtf/HashMap.h"} = 1;
265 $headerIncludes{"v8.h"} = 1;
267 my $headerClassInclude = GetHeaderClassInclude($implClassName);
268 $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
270 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
272 foreach my $headerInclude (sort keys(%headerIncludes)) {
273 if ($headerInclude =~ /wtf|v8\.h/) {
274 push(@headerContent, "#include \<${headerInclude}\>\n");
276 push(@headerContent, "#include \"${headerInclude}\"\n");
280 push(@headerContent, "\nnamespace WebCore {\n");
281 push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
282 if ($svgNativeType) {
283 if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
284 push(@headerContent, "\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
286 push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
290 push(@headerContent, "\n");
291 push(@headerContent, "class FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect";
292 push(@headerContent, "class Dictionary;\n") if IsConstructorTemplate($dataNode, "Event");
294 my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
295 if ($dataNode->extendedAttributes->{"NamedConstructor"}) {
296 push(@headerContent, <<END);
297 class V8${nativeType}Constructor {
299 static v8::Persistent<v8::FunctionTemplate> GetTemplate();
300 static WrapperTypeInfo info;
306 push(@headerContent, "class $className {\n");
307 push(@headerContent, "public:\n");
309 push(@headerContent, " static const bool hasDependentLifetime = ");
310 if ($hasDependentLifetime) {
311 push(@headerContent, "true;\n");
312 } elsif (@{$dataNode->parents}) {
313 # Even if this type doesn't have the V8DependentLifetime attribute its parents may.
314 # Let the compiler statically determine this for us.
316 foreach (@{$dataNode->parents}) {
317 my $parent = $codeGenerator->StripModule($_);
318 next if $parent eq "EventTarget";
319 $headerIncludes{"V8${parent}.h"} = 1;
320 push(@headerContent, "${separator}V8${parent}::hasDependentLifetime");
323 push(@headerContent, ";\n");
325 push(@headerContent, "false;\n");
328 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
329 my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
330 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
331 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
333 push(@headerContent, <<END);
334 static bool HasInstance(v8::Handle<v8::Value>);
335 static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
336 static v8::Persistent<v8::FunctionTemplate> GetTemplate();
337 static ${nativeType}* toNative(v8::Handle<v8::Object> object)
339 return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
341 inline static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
342 static void derefObject(void*);
343 static WrapperTypeInfo info;
345 if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
346 push(@headerContent, " static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
349 if ($implClassName eq "DOMWindow") {
350 push(@headerContent, <<END);
351 static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
355 if ($implClassName eq "HTMLDocument") {
356 push(@headerContent, <<END);
357 static v8::Local<v8::Object> WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl);
358 static v8::Handle<v8::Value> GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key);
362 my @enabledAtRuntime;
363 foreach my $function (@{$dataNode->functions}) {
364 my $name = $function->signature->name;
365 my $attrExt = $function->signature->extendedAttributes;
367 if (($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) && !$attrExt->{"ImplementedBy"} && $function->{overloadIndex} == 1) {
368 my $conditionalString = GenerateConditionalString($function->signature);
369 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
370 push(@headerContent, <<END);
371 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
373 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
376 if ($attrExt->{"V8EnabledAtRuntime"}) {
377 push(@enabledAtRuntime, $function);
381 if (IsConstructable($dataNode)) {
382 push(@headerContent, <<END);
383 static v8::Handle<v8::Value> constructorCallback(const v8::Arguments&);
387 foreach my $attribute (@{$dataNode->attributes}) {
388 my $name = $attribute->signature->name;
389 my $attrExt = $attribute->signature->extendedAttributes;
390 my $conditionalString = GenerateConditionalString($attribute->signature);
391 if (($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"} ||
392 $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) &&
393 !$attrExt->{"ImplementedBy"}) {
394 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
395 push(@headerContent, <<END);
396 static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);
398 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
400 if (($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"} ||
401 $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) &&
402 !$attrExt->{"ImplementedBy"}) {
403 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
404 push(@headerContent, <<END);
405 static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);
407 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
409 if ($attrExt->{"V8EnabledAtRuntime"}) {
410 push(@enabledAtRuntime, $attribute);
414 GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
415 GenerateHeaderCustomCall($dataNode);
416 GenerateHeaderCustomInternalFieldIndices($dataNode);
418 if ($dataNode->extendedAttributes->{"CheckSecurity"}) {
419 push(@headerContent, <<END);
420 static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
421 static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
425 push(@headerContent, <<END);
427 static v8::Handle<v8::Object> wrapSlow(${nativeType}*);
432 push(@headerContent, <<END);
433 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput})
436 push(@headerContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
437 my $getCachedWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getCachedWrapper(impl)" : "${domMapFunction}.get(impl)";
438 push(@headerContent, <<END);
439 v8::Handle<v8::Object> wrapper = $getCachedWrapper;
440 if (!wrapper.IsEmpty())
443 push(@headerContent, " }\n") if IsDOMNodeType($interfaceName);
444 push(@headerContent, <<END);
445 return ${className}::wrapSlow(impl);
449 if ($interfaceName eq 'Element') {
450 # Do not generate toV8() for performance optimization.
451 } elsif (!($dataNode->extendedAttributes->{"CustomToJSObject"} or $dataNode->extendedAttributes->{"V8CustomToJSObject"})) {
452 push(@headerContent, <<END);
454 inline v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectParameter})
458 return ${className}::wrap(impl${forceNewObjectCall});
461 } elsif ($interfaceName ne 'Node') {
462 push(@headerContent, <<END);
464 v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
467 push(@headerContent, <<END);
469 v8::Handle<v8::Value> toV8Slow(Node*, bool);
471 inline v8::Handle<v8::Value> toV8(Node* impl, bool forceNewObject = false)
475 if (UNLIKELY(forceNewObject))
476 return toV8Slow(impl, forceNewObject);
477 v8::Handle<v8::Value> wrapper = V8DOMWrapper::getCachedWrapper(impl);
478 if (!wrapper.IsEmpty())
480 return toV8Slow(impl, false);
485 if (IsRefPtrType($implClassName)) {
486 push(@headerContent, <<END);
487 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl${forceNewObjectParameter})
489 return toV8(impl.get()${forceNewObjectCall});
494 if (IsConstructorTemplate($dataNode, "Event")) {
495 push(@headerContent, "\nbool fill${implClassName}Init(${implClassName}Init&, const Dictionary&);\n");
498 push(@headerContent, "\n}\n\n");
499 push(@headerContent, "#endif // $className" . "_h\n");
501 my $conditionalString = GenerateConditionalString($dataNode);
502 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
505 sub GetInternalFields
507 my $dataNode = shift;
508 my $name = $dataNode->name;
510 my @customInternalFields = ();
511 # We can't ask whether a parent type has a given extendedAttribute,
512 # so special-case AbstractWorker and WorkerContext to include all sub-types.
513 # Event listeners on DOM nodes are explicitly supported in the GC controller.
514 # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't.
515 if (!IsNodeSubType($dataNode)
516 && ($dataNode->extendedAttributes->{"EventTarget"}
517 || $dataNode->extendedAttributes->{"IsWorkerContext"}
518 || IsSubType($dataNode, "AbstractWorker")
519 || $name eq "SVGElementInstance")) {
520 push(@customInternalFields, "eventListenerCacheIndex");
523 if ($name eq "DOMWindow") {
524 push(@customInternalFields, "enteredIsolatedWorldIndex");
526 return @customInternalFields;
529 sub GetHeaderClassInclude
531 my $className = shift;
532 if ($className =~ /SVGPathSeg/) {
533 $className =~ s/Abs|Rel//;
535 return "wtf/${className}.h" if IsTypedArrayType($className);
536 return "" if ($codeGenerator->AvoidInclusionOfType($className));
537 return "${className}.h";
540 sub GenerateHeaderCustomInternalFieldIndices
542 my $dataNode = shift;
543 my @customInternalFields = GetInternalFields($dataNode);
544 my $customFieldCounter = 0;
545 foreach my $customInternalField (@customInternalFields) {
546 push(@headerContent, <<END);
547 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
549 $customFieldCounter++;
551 push(@headerContent, <<END);
552 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
556 my %indexerSpecialCases = (
558 "HTMLAppletElement" => 1,
559 "HTMLEmbedElement" => 1,
560 "HTMLObjectElement" => 1
563 sub GenerateHeaderNamedAndIndexedPropertyAccessors
565 my $dataNode = shift;
566 my $interfaceName = $dataNode->name;
567 my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"IndexedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
568 my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"CustomIndexedSetter"} && !$dataNode->extendedAttributes->{"NumericIndexedGetter"};
569 my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"NamedGetter"} || $dataNode->extendedAttributes->{"CustomNamedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
570 my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"CustomNamedSetter"};
571 my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
572 my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomEnumerateProperty"};
573 if ($interfaceName eq "HTMLOptionsCollection") {
574 $interfaceName = "HTMLCollection";
575 $hasCustomIndexedGetter = 1;
576 $hasCustomNamedGetter = 1;
578 if ($interfaceName eq "DOMWindow") {
579 $hasCustomDeleters = 0;
580 $hasCustomEnumerator = 0;
582 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
583 $hasCustomNamedGetter = 1;
585 if ($interfaceName eq "HTMLDocument") {
586 $hasCustomNamedGetter = 0;
587 $hasCustomIndexedGetter = 0;
589 my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
591 if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
592 push(@headerContent, <<END);
593 static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
597 if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
598 push(@headerContent, <<END);
599 static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
602 if ($hasCustomDeleters) {
603 push(@headerContent, <<END);
604 static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
607 if ($hasCustomNamedGetter) {
608 push(@headerContent, <<END);
609 static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
612 if ($hasCustomNamedSetter) {
613 push(@headerContent, <<END);
614 static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
617 if ($hasCustomDeleters) {
618 push(@headerContent, <<END);
619 static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
622 if ($hasCustomEnumerator) {
623 push(@headerContent, <<END);
624 static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
625 static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
630 sub GenerateHeaderCustomCall
632 my $dataNode = shift;
634 if ($dataNode->extendedAttributes->{"CustomCall"}) {
635 push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
637 if ($dataNode->name eq "Event") {
638 push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
639 push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);\n");
641 if ($dataNode->name eq "Location") {
642 push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
643 push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
644 push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
648 sub GenerateSetDOMException
653 $result .= $indent . "if (UNLIKELY(ec)) {\n";
654 $result .= $indent . " V8Proxy::setDOMException(ec);\n";
655 $result .= $indent . " return v8::Handle<v8::Value>();\n";
656 $result .= $indent . "}\n";
663 my $dataNode = shift;
664 my $parentType = shift;
665 return 1 if ($dataNode->name eq $parentType);
666 foreach (@allParents) {
667 my $parent = $codeGenerator->StripModule($_);
668 return 1 if $parent eq $parentType;
675 my $dataNode = shift;
676 return IsSubType($dataNode, "Node");
679 sub IsVisibleAcrossOrigins
681 my $dataNode = shift;
682 return $dataNode->extendedAttributes->{"CheckSecurity"} && !($dataNode->name eq "DOMWindow");
687 my $dataNode = shift;
689 return $dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"Constructor"} || $dataNode->extendedAttributes->{"ConstructorTemplate"};
692 sub IsConstructorTemplate
694 my $dataNode = shift;
695 my $template = shift;
697 return $dataNode->extendedAttributes->{"ConstructorTemplate"} && $dataNode->extendedAttributes->{"ConstructorTemplate"} eq $template;
700 sub GenerateDomainSafeFunctionGetter
702 my $function = shift;
703 my $implClassName = shift;
705 my $className = "V8" . $implClassName;
706 my $funcName = $function->signature->name;
708 my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
709 if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
710 $signature = "v8::Local<v8::Signature>()";
713 my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature);
715 push(@implContentDecls, <<END);
716 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
718 INC_STATS(\"DOM.$implClassName.$funcName._get\");
719 static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
720 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
721 if (holder.IsEmpty()) {
722 // can only reach here by 'object.__proto__.func', and it should passed
723 // domain security check already
724 return privateTemplate->GetFunction();
726 ${implClassName}* imp = ${className}::toNative(holder);
727 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
728 static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
729 return sharedTemplate->GetFunction();
731 return privateTemplate->GetFunction();
737 sub GenerateConstructorGetter
739 my $dataNode = shift;
740 my $implClassName = shift;
742 push(@implContentDecls, <<END);
743 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
745 INC_STATS(\"DOM.$implClassName.constructors._get\");
746 v8::Handle<v8::Value> data = info.Data();
747 ASSERT(data->IsExternal() || data->IsNumber());
748 WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data);
751 if ($implClassName eq "DOMWindow") {
752 push(@implContentDecls, <<END);
753 // Get the proxy corresponding to the DOMWindow if possible to
754 // make sure that the constructor function is constructed in the
755 // context of the DOMWindow and not in the context of the caller.
756 return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder()));
758 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
759 push(@implContentDecls, <<END);
760 return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder()));
763 push(@implContentDecls, " return v8::Handle<v8::Value>();");
766 push(@implContentDecls, <<END);
772 sub GenerateNormalAttrGetter
774 my $attribute = shift;
775 my $dataNode = shift;
776 my $implClassName = shift;
777 my $interfaceName = shift;
779 my $attrExt = $attribute->signature->extendedAttributes;
780 my $attrName = $attribute->signature->name;
781 my $attrType = GetTypeFromSignature($attribute->signature);
782 my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
784 my $getterStringUsesImp = $implClassName ne "SVGNumber";
785 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
788 my $conditionalString = GenerateConditionalString($attribute->signature);
789 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
791 push(@implContentDecls, <<END);
792 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
794 INC_STATS(\"DOM.$implClassName.$attrName._get\");
797 if ($svgNativeType) {
798 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
799 if ($svgWrappedNativeType =~ /List/) {
800 push(@implContentDecls, <<END);
801 $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
804 push(@implContentDecls, <<END);
805 $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());
806 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
808 if ($getterStringUsesImp) {
809 push(@implContentDecls, <<END);
810 $svgWrappedNativeType* imp = &impInstance;
814 } elsif ($attrExt->{"V8OnProto"} || $attrExt->{"V8Unforgeable"}) {
815 if ($interfaceName eq "DOMWindow") {
816 push(@implContentDecls, <<END);
817 v8::Handle<v8::Object> holder = info.Holder();
820 # perform lookup first
821 push(@implContentDecls, <<END);
822 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
823 if (holder.IsEmpty())
824 return v8::Handle<v8::Value>();
827 push(@implContentDecls, <<END);
828 ${implClassName}* imp = V8${implClassName}::toNative(holder);
831 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
832 my $url = $attribute->signature->extendedAttributes->{"URL"};
833 if ($getterStringUsesImp && $reflect && !$url && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
834 # Generate super-compact call for regular attribute getter:
835 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
836 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
837 AddToImplIncludes("${namespace}.h");
838 push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n");
839 push(@implContentDecls, "}\n\n");
840 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
842 # Skip the rest of the function!
844 if ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
845 push(@implContentDecls, <<END);
846 v8::Handle<v8::String> propertyName = v8::String::NewSymbol("${attrName}");
847 v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(propertyName);
848 if (!value.IsEmpty())
852 push(@implContentDecls, <<END);
853 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
857 # Generate security checks if necessary
858 if ($attribute->signature->extendedAttributes->{"CheckSecurityForNode"}) {
859 push(@implContentDecls, " if (!V8BindingSecurity::shouldAllowAccessToNode(V8BindingState::Only(), imp->" . $attribute->signature->name . "()))\n return v8::Handle<v8::Value>();\n\n");
862 my $useExceptions = 1 if @{$attribute->getterExceptions};
863 if ($useExceptions) {
864 AddToImplIncludes("ExceptionCode.h");
865 push(@implContentDecls, " ExceptionCode ec = 0;\n");
868 my $returnType = GetTypeFromSignature($attribute->signature);
871 if ($getterStringUsesImp) {
872 my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
874 push(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentDecls, " ", 0, 0));
876 push(@arguments, "ec") if $useExceptions;
877 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
878 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
879 AddToImplIncludes("${implementedBy}.h");
880 unshift(@arguments, "imp");
881 $functionName = "${implementedBy}::${functionName}";
883 $functionName = "imp->${functionName}";
885 $getterString = "${functionName}(" . join(", ", @arguments) . ")";
887 $getterString = "impInstance";
893 if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
894 push(@implContentDecls, " if (!imp->document())\n");
895 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
898 if ($useExceptions) {
899 if ($nativeType =~ /^V8Parameter/) {
900 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $getterString) . ";\n");
902 push(@implContentDecls, " $nativeType v = $getterString;\n");
904 push(@implContentDecls, GenerateSetDOMException(" "));
906 if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
907 push(@implContentDecls, " if (state.hadException())\n");
908 push(@implContentDecls, " return throwError(state.exception());\n");
912 $result .= ".release()" if (IsRefPtrType($returnType));
914 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
915 $result = $getterString;
916 # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
917 $result = "static_pointer_cast<SVGAnimatedEnumeration>($result)" if $returnType eq "SVGAnimatedEnumeration";
920 # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
921 # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
922 # the newly created wrapper into an internal field of the holder object.
923 if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"})
924 && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow"
925 && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) {
926 AddIncludesForType($returnType);
927 # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
928 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
929 push(@implContentDecls, " RefPtr<$returnType> result = ${getterString};\n");
930 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
931 push(@implContentDecls, " v8::Handle<v8::Value> wrapper = result.get() ? ${domMapFunction}.get(result.get()) : v8::Handle<v8::Object>();\n");
932 push(@implContentDecls, " if (wrapper.IsEmpty()) {\n");
933 push(@implContentDecls, " wrapper = toV8(result.get());\n");
934 push(@implContentDecls, " if (!wrapper.IsEmpty())\n");
935 if ($dataNode->name eq "DOMWindow") {
936 push(@implContentDecls, " V8DOMWrapper::setNamedHiddenWindowReference(imp->frame(), \"${attrName}\", wrapper);\n");
938 push(@implContentDecls, " V8DOMWrapper::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n");
940 push(@implContentDecls, " }\n");
941 push(@implContentDecls, " return wrapper;\n");
942 push(@implContentDecls, "}\n\n");
943 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
947 if ($codeGenerator->IsSVGAnimatedType($implClassName) and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) {
948 AddToImplIncludes("V8$attrType.h");
949 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
950 # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
951 push(@implContentDecls, " return toV8(static_cast<$svgNativeType*>($result));\n");
952 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $implClassName =~ /List$/) {
953 AddToImplIncludes("V8$attrType.h");
954 AddToImplIncludes("SVGPropertyTearOff.h");
955 my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
956 if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
957 my $getter = $result;
958 $getter =~ s/imp->//;
961 my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter);
963 my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
964 if ($selfIsTearOffType) {
965 AddToImplIncludes("SVGStaticPropertyWithParentTearOff.h");
966 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /;
968 if ($result =~ /matrix/ and $implClassName eq "SVGTransform") {
969 # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
970 # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
971 $result =~ s/matrix/svgMatrix/;
974 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(wrapper, $result, $updateMethod)));\n");
976 AddToImplIncludes("SVGStaticPropertyTearOff.h");
977 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
979 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(imp, $result, $updateMethod)));\n");
981 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
982 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(imp, $result)));\n");
983 } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
984 push(@implContentDecls, " return toV8(WTF::getPtr($result));\n");
986 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create($result)));\n");
989 if ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
990 my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
991 push(@implContentDecls, <<END);
992 SerializedScriptValue* serialized = imp->${getterFunc}();
993 value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::Null());
994 info.Holder()->SetHiddenValue(propertyName, value);
998 push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n");
1002 push(@implContentDecls, "}\n\n"); # end of getter
1003 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1006 sub GenerateNormalAttrSetter
1008 my $attribute = shift;
1009 my $dataNode = shift;
1010 my $implClassName = shift;
1011 my $interfaceName = shift;
1013 AddToImplIncludes("V8BindingMacros.h");
1015 my $attrName = $attribute->signature->name;
1016 my $attrExt = $attribute->signature->extendedAttributes;
1018 my $conditionalString = GenerateConditionalString($attribute->signature);
1019 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1021 push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
1022 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
1024 # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
1025 # interface type, then if the incoming value does not implement that interface, a TypeError is
1026 # thrown rather than silently passing NULL to the C++ code.
1027 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
1028 # strings and numbers, so do not throw TypeError if the attribute is of these types.
1029 if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
1030 my $argType = GetTypeFromSignature($attribute->signature);
1031 if (IsWrapperType($argType)) {
1032 push(@implContentDecls, " if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value)) {\n");
1033 push(@implContentDecls, " V8Proxy::throwTypeError();\n");
1034 push(@implContentDecls, " return;\n");
1035 push(@implContentDecls, " }\n");
1039 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
1040 if ($svgNativeType) {
1041 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1042 if ($svgWrappedNativeType =~ /List$/) {
1043 push(@implContentDecls, <<END);
1044 $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
1047 AddToImplIncludes("ExceptionCode.h");
1048 push(@implContentDecls, " $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());\n");
1049 push(@implContentDecls, " if (wrapper->role() == AnimValRole) {\n");
1050 push(@implContentDecls, " V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR);\n");
1051 push(@implContentDecls, " return;\n");
1052 push(@implContentDecls, " }\n");
1053 push(@implContentDecls, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1054 push(@implContentDecls, " $svgWrappedNativeType* imp = &impInstance;\n");
1056 } elsif ($attrExt->{"V8OnProto"}) {
1057 if ($interfaceName eq "DOMWindow") {
1058 push(@implContentDecls, <<END);
1059 v8::Handle<v8::Object> holder = info.Holder();
1062 # perform lookup first
1063 push(@implContentDecls, <<END);
1064 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
1065 if (holder.IsEmpty())
1069 push(@implContentDecls, <<END);
1070 ${implClassName}* imp = V8${implClassName}::toNative(holder);
1073 my $attrType = GetTypeFromSignature($attribute->signature);
1074 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1075 if ($reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
1076 # Generate super-compact call for regular attribute setter:
1077 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
1078 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1079 AddToImplIncludes("${namespace}.h");
1080 push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n");
1081 push(@implContentDecls, "}\n\n");
1082 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1084 # Skip the rest of the function!
1087 push(@implContentDecls, <<END);
1088 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
1092 my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
1093 if ($attribute->signature->type eq "EventListener") {
1094 if ($dataNode->name eq "DOMWindow") {
1095 push(@implContentDecls, " if (!imp->document())\n");
1096 push(@implContentDecls, " return;\n");
1099 my $value = JSValueToNative($attribute->signature, "value");
1100 if ($nativeType =~ /^V8Parameter/) {
1101 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
1103 push(@implContentDecls, " $nativeType v = $value;\n");
1108 my $returnType = GetTypeFromSignature($attribute->signature);
1109 if (IsRefPtrType($returnType)) {
1110 $result = "WTF::getPtr(" . $result . ")";
1113 my $useExceptions = 1 if @{$attribute->setterExceptions};
1115 if ($useExceptions) {
1116 AddToImplIncludes("ExceptionCode.h");
1117 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1120 if ($implClassName eq "SVGNumber") {
1121 push(@implContentDecls, " *imp = $result;\n");
1123 if ($attribute->signature->type eq "EventListener") {
1124 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
1125 AddToImplIncludes("V8AbstractEventListener.h");
1126 if (!IsNodeSubType($dataNode)) {
1127 push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n");
1129 if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
1130 AddToImplIncludes("V8EventListenerList.h");
1131 AddToImplIncludes("V8WorkerContextErrorHandler.h");
1132 push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
1133 } elsif ($interfaceName eq "DOMWindow" and $attribute->signature->name eq "onerror") {
1134 AddToImplIncludes("V8EventListenerList.h");
1135 AddToImplIncludes("V8WindowErrorHandler.h");
1136 push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WindowErrorHandler>(value, true)");
1138 push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)");
1140 push(@implContentDecls, ", ec") if $useExceptions;
1141 push(@implContentDecls, ");\n");
1143 my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute);
1145 push(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentDecls, " ", 1, 0));
1147 push(@arguments, $result);
1148 push(@arguments, "ec") if $useExceptions;
1149 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
1150 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
1151 AddToImplIncludes("${implementedBy}.h");
1152 unshift(@arguments, "imp");
1153 $functionName = "${implementedBy}::${functionName}";
1155 $functionName = "imp->${functionName}";
1157 push(@implContentDecls, " ${functionName}(" . join(", ", @arguments) . ");\n");
1161 if ($useExceptions) {
1162 push(@implContentDecls, " if (UNLIKELY(ec))\n");
1163 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
1166 if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
1167 push(@implContentDecls, " if (state.hadException())\n");
1168 push(@implContentDecls, " throwError(state.exception());\n");
1171 if ($svgNativeType) {
1172 if ($useExceptions) {
1173 push(@implContentDecls, " if (!ec)\n");
1174 push(@implContentDecls, " wrapper->commitChange();\n");
1176 push(@implContentDecls, " wrapper->commitChange();\n");
1180 if ($attribute->signature->type eq "SerializedScriptValue" && $attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1181 push(@implContentDecls, <<END);
1182 info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // Invalidate the cached value.
1186 push(@implContentDecls, " return;\n");
1187 push(@implContentDecls, "}\n\n"); # end of setter
1188 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1191 sub GetFunctionTemplateCallbackName
1193 my $function = shift;
1194 my $interfaceName = shift;
1196 my $name = $function->signature->name;
1198 if ($function->signature->extendedAttributes->{"Custom"} ||
1199 $function->signature->extendedAttributes->{"V8Custom"}) {
1200 if ($function->signature->extendedAttributes->{"Custom"} &&
1201 $function->signature->extendedAttributes->{"V8Custom"}) {
1202 die "Custom and V8Custom should be mutually exclusive!"
1204 return "V8${interfaceName}::${name}Callback";
1206 return "${interfaceName}Internal::${name}Callback";
1210 sub GenerateNewFunctionTemplate
1212 my $function = shift;
1213 my $interfaceName = shift;
1214 my $signature = shift;
1216 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1217 return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
1220 sub GenerateEventListenerCallback
1222 my $implClassName = shift;
1223 my $requiresHiddenDependency = shift;
1224 my $functionName = shift;
1225 my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
1226 my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1227 my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1229 push(@implContentDecls, <<END);
1230 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1232 INC_STATS("DOM.${implClassName}.${functionName}EventListener()");
1233 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType});
1235 V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue());
1237 if ($requiresHiddenDependency) {
1238 push(@implContentDecls, <<END);
1239 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex);
1242 push(@implContentDecls, <<END);
1244 return v8::Undefined();
1250 sub GenerateParametersCheckExpression
1252 my $numParameters = shift;
1253 my $function = shift;
1255 my @andExpression = ();
1256 push(@andExpression, "args.Length() == $numParameters");
1257 my $parameterIndex = 0;
1258 foreach my $parameter (@{$function->parameters}) {
1259 last if $parameterIndex >= $numParameters;
1260 my $value = "args[$parameterIndex]";
1261 my $type = GetTypeFromSignature($parameter);
1263 # Only DOMString or wrapper types are checked.
1264 # For DOMString, Null, Undefined and any Object are accepted too, as
1265 # these are acceptable values for a DOMString argument (any Object can
1266 # be converted to a string via .toString).
1267 if ($codeGenerator->IsStringType($type)) {
1268 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
1269 } elsif ($parameter->extendedAttributes->{"Callback"}) {
1270 # For Callbacks only checks if the value is null or object.
1271 push(@andExpression, "(${value}->IsNull() || ${value}->IsObject())");
1272 } elsif (IsArrayType($type)) {
1273 # FIXME: Add proper support for T[], T[]?, sequence<T>.
1274 push(@andExpression, "(${value}->IsNull() || ${value}->IsArray())");
1275 } elsif (IsWrapperType($type)) {
1276 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))");
1281 my $res = join(" && ", @andExpression);
1282 $res = "($res)" if @andExpression > 1;
1286 sub GenerateFunctionParametersCheck
1288 my $function = shift;
1290 my @orExpression = ();
1291 my $numParameters = 0;
1292 foreach my $parameter (@{$function->parameters}) {
1293 if ($parameter->extendedAttributes->{"Optional"}) {
1294 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1298 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1299 return join(" || ", @orExpression);
1302 sub GenerateOverloadedFunctionCallback
1304 my $function = shift;
1305 my $dataNode = shift;
1306 my $implClassName = shift;
1308 # Generate code for choosing the correct overload to call. Overloads are
1309 # chosen based on the total number of arguments passed and the type of
1310 # values passed in non-primitive argument slots. When more than a single
1311 # overload is applicable, precedence is given according to the order of
1312 # declaration in the IDL.
1314 my $name = $function->signature->name;
1315 my $conditionalString = GenerateConditionalString($function->signature);
1316 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1317 push(@implContentDecls, <<END);
1318 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1320 INC_STATS(\"DOM.$implClassName.$name\");
1323 foreach my $overload (@{$function->{overloads}}) {
1324 my $parametersCheck = GenerateFunctionParametersCheck($overload);
1325 push(@implContentDecls, " if ($parametersCheck)\n");
1326 push(@implContentDecls, " return ${name}$overload->{overloadIndex}Callback(args);\n");
1328 push(@implContentDecls, <<END);
1329 V8Proxy::throwTypeError();
1330 return notHandledByInterceptor();
1332 push(@implContentDecls, "}\n\n");
1333 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1336 sub GenerateFunctionCallback
1338 my $function = shift;
1339 my $dataNode = shift;
1340 my $implClassName = shift;
1342 my $interfaceName = $dataNode->name;
1343 my $name = $function->signature->name;
1345 if (@{$function->{overloads}} > 1) {
1346 # Append a number to an overloaded method's name to make it unique:
1347 $name = $name . $function->{overloadIndex};
1350 # Adding and removing event listeners are not standard callback behavior,
1351 # but they are extremely consistent across the various classes that take event listeners,
1352 # so we can generate them as a "special case".
1353 if ($name eq "addEventListener") {
1354 GenerateEventListenerCallback($implClassName, !IsNodeSubType($dataNode), "add");
1356 } elsif ($name eq "removeEventListener") {
1357 GenerateEventListenerCallback($implClassName, !IsNodeSubType($dataNode), "remove");
1361 my $conditionalString = GenerateConditionalString($function->signature);
1362 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1363 push(@implContentDecls, <<END);
1364 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1366 INC_STATS(\"DOM.$implClassName.$name\");
1369 push(@implContentDecls, GenerateArgumentsCountCheck($function, $dataNode));
1371 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
1373 if ($svgNativeType) {
1374 my $nativeClassName = GetNativeType($implClassName);
1375 if ($implClassName =~ /List$/) {
1376 push(@implContentDecls, " $nativeClassName imp = V8${implClassName}::toNative(args.Holder());\n");
1378 AddToImplIncludes("ExceptionCode.h");
1379 push(@implContentDecls, " $nativeClassName wrapper = V8${implClassName}::toNative(args.Holder());\n");
1380 push(@implContentDecls, " if (wrapper->role() == AnimValRole) {\n");
1381 push(@implContentDecls, " V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR);\n");
1382 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1383 push(@implContentDecls, " }\n");
1384 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1385 push(@implContentDecls, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1386 push(@implContentDecls, " $svgWrappedNativeType* imp = &impInstance;\n");
1388 } elsif (!$function->isStatic) {
1389 push(@implContentDecls, <<END);
1390 ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
1394 # Check domain security if needed
1395 if (($dataNode->extendedAttributes->{"CheckSecurity"}
1396 || $interfaceName eq "DOMWindow")
1397 && !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
1398 # We have not find real use cases yet.
1399 push(@implContentDecls, <<END);
1400 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
1401 return v8::Handle<v8::Value>();
1405 my $raisesExceptions = @{$function->raisesExceptions};
1406 if (!$raisesExceptions) {
1407 foreach my $parameter (@{$function->parameters}) {
1408 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1409 $raisesExceptions = 1;
1414 if ($raisesExceptions) {
1415 AddToImplIncludes("ExceptionCode.h");
1416 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1417 push(@implContentDecls, " {\n");
1418 # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1419 # of objects (like Strings) declared later, causing compile errors. The block scope ends
1420 # right before the label 'fail:'.
1423 if ($function->signature->extendedAttributes->{"CheckSecurityForNode"}) {
1424 push(@implContentDecls, " if (!V8BindingSecurity::shouldAllowAccessToNode(V8BindingState::Only(), imp->" . $function->signature->name . "(ec)))\n");
1425 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1429 my ($parameterCheckString, $paramIndex) = GenerateParametersCheck($function, $implClassName);
1430 push(@implContentDecls, $parameterCheckString);
1432 # Build the function call string.
1433 push(@implContentDecls, GenerateFunctionCallString($function, $paramIndex, " ", $implClassName));
1435 if ($raisesExceptions) {
1436 push(@implContentDecls, " }\n");
1437 push(@implContentDecls, " fail:\n");
1438 push(@implContentDecls, " V8Proxy::setDOMException(ec);\n");
1439 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
1442 push(@implContentDecls, "}\n\n");
1443 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1446 sub GenerateCallWith
1448 my $callWith = shift;
1449 return () unless $callWith;
1450 my $outputArray = shift;
1452 my $returnVoid = shift;
1453 my $emptyContext = shift;
1454 my $function = shift;
1457 if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) {
1458 if ($emptyContext) {
1459 push(@$outputArray, $indent . "EmptyScriptState state;\n");
1460 push(@callWithArgs, "&state");
1462 push(@$outputArray, $indent . "ScriptState* state = ScriptState::current();\n");
1463 push(@$outputArray, $indent . "if (!state)\n");
1464 push(@$outputArray, $indent . " return" . ($returnVoid ? "" : " v8::Undefined()") . ";\n");
1465 push(@callWithArgs, "state");
1468 if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptExecutionContext")) {
1469 push(@$outputArray, $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n");
1470 push(@$outputArray, $indent . "if (!scriptContext)\n");
1471 push(@$outputArray, $indent . " return" . ($returnVoid ? "" : " v8::Undefined()") . ";\n");
1472 push(@callWithArgs, "scriptContext");
1474 if ($function and $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments")) {
1475 push(@$outputArray, $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, " . @{$function->parameters} . "));\n");
1476 push(@callWithArgs, "scriptArguments");
1477 AddToImplIncludes("ScriptArguments.h");
1479 if ($codeGenerator->ExtendedAttributeContains($callWith, "CallStack")) {
1480 push(@$outputArray, $indent . "RefPtr<ScriptCallStack> callStack(createScriptCallStackForInspector());\n");
1481 push(@$outputArray, $indent . "if (!callStack)\n");
1482 push(@$outputArray, $indent . " return v8::Undefined();\n");
1483 push(@callWithArgs, "callStack");
1484 AddToImplIncludes("ScriptCallStack.h");
1485 AddToImplIncludes("ScriptCallStackFactory.h");
1487 return @callWithArgs;
1490 sub GenerateArgumentsCountCheck
1492 my $function = shift;
1493 my $dataNode = shift;
1495 my $numMandatoryParams = 0;
1496 my $optionalSeen = 0;
1497 foreach my $param (@{$function->parameters}) {
1498 if ($param->extendedAttributes->{"Optional"}) {
1501 die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if $optionalSeen;
1502 $numMandatoryParams++;
1506 my $argumentsCountCheckString = "";
1507 if ($numMandatoryParams >= 1) {
1508 $argumentsCountCheckString .= " if (args.Length() < $numMandatoryParams)\n";
1509 $argumentsCountCheckString .= " return throwError(\"Not enough arguments\", V8Proxy::TypeError);\n";
1511 return $argumentsCountCheckString;
1514 sub GenerateParametersCheck
1516 my $function = shift;
1517 my $implClassName = shift;
1519 my $parameterCheckString = "";
1521 foreach my $parameter (@{$function->parameters}) {
1522 TranslateParameter($parameter);
1524 my $parameterName = $parameter->name;
1526 # Optional arguments with [Optional] should generate an early call with fewer arguments.
1527 # Optional arguments with [Optional=...] should not generate the early call.
1528 my $optional = $parameter->extendedAttributes->{"Optional"};
1529 if ($optional && $optional ne "DefaultIsUndefined" && $optional ne "DefaultIsNullString" && !$parameter->extendedAttributes->{"Callback"}) {
1530 $parameterCheckString .= " if (args.Length() <= $paramIndex) {\n";
1531 my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName);
1532 $parameterCheckString .= $functionCall;
1533 $parameterCheckString .= " }\n";
1536 my $parameterDefaultPolicy = "DefaultIsUndefined";
1537 if ($optional and $optional eq "DefaultIsNullString") {
1538 $parameterDefaultPolicy = "DefaultIsNullString";
1541 AddToImplIncludes("ExceptionCode.h");
1542 my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1543 if ($parameter->extendedAttributes->{"Callback"}) {
1544 my $className = GetCallbackClassName($parameter->type);
1545 AddToImplIncludes("$className.h");
1547 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $parameterName;\n";
1548 $parameterCheckString .= " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n";
1549 $parameterCheckString .= " if (!args[$paramIndex]->IsObject())\n";
1550 $parameterCheckString .= " return throwError(TYPE_MISMATCH_ERR);\n";
1551 $parameterCheckString .= " $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n";
1552 $parameterCheckString .= " }\n";
1554 $parameterCheckString .= " if (args.Length() <= $paramIndex || !args[$paramIndex]->IsObject())\n";
1555 $parameterCheckString .= " return throwError(TYPE_MISMATCH_ERR);\n";
1556 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n";
1558 } elsif ($parameter->type eq "SerializedScriptValue") {
1559 AddToImplIncludes("SerializedScriptValue.h");
1560 $parameterCheckString .= " bool ${parameterName}DidThrow = false;\n";
1561 $parameterCheckString .= " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow);\n";
1562 $parameterCheckString .= " if (${parameterName}DidThrow)\n";
1563 $parameterCheckString .= " return v8::Undefined();\n";
1564 } elsif (TypeCanFailConversion($parameter)) {
1565 $parameterCheckString .= " $nativeType $parameterName = " .
1566 JSValueToNative($parameter, "args[$paramIndex]") . ";\n";
1567 $parameterCheckString .= " if (UNLIKELY(!$parameterName)) {\n";
1568 $parameterCheckString .= " ec = TYPE_MISMATCH_ERR;\n";
1569 $parameterCheckString .= " goto fail;\n";
1570 $parameterCheckString .= " }\n";
1571 } elsif ($nativeType =~ /^V8Parameter/) {
1572 my $value = JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterDefaultPolicy)");
1573 $parameterCheckString .= " " . ConvertToV8Parameter($parameter, $nativeType, $parameterName, $value) . "\n";
1575 AddToImplIncludes("V8BindingMacros.h");
1576 # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
1577 # interface type, then if the incoming value does not implement that interface, a TypeError
1578 # is thrown rather than silently passing NULL to the C++ code.
1579 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
1580 # to both strings and numbers, so do not throw TypeError if the argument is of these
1582 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1583 my $argValue = "args[$paramIndex]";
1584 my $argType = GetTypeFromSignature($parameter);
1585 if (IsWrapperType($argType)) {
1586 $parameterCheckString .= " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue)) {\n";
1587 $parameterCheckString .= " V8Proxy::throwTypeError();\n";
1588 $parameterCheckString .= " return notHandledByInterceptor();\n";
1589 $parameterCheckString .= " }\n";
1592 $parameterCheckString .= " EXCEPTION_BLOCK($nativeType, $parameterName, " .
1593 JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterDefaultPolicy)") . ");\n";
1594 if ($nativeType eq 'Dictionary') {
1595 $parameterCheckString .= " if (args.Length() > $paramIndex && !$parameterName.isUndefinedOrNull() && !$parameterName.isObject()) {\n";
1596 $parameterCheckString .= " ec = TYPE_MISMATCH_ERR;\n";
1597 $parameterCheckString .= " V8Proxy::setDOMException(ec);\n";
1598 $parameterCheckString .= " return throwError(\"Not an object.\", V8Proxy::TypeError);\n";
1599 $parameterCheckString .= " }\n";
1603 if ($parameter->extendedAttributes->{"IsIndex"}) {
1604 $parameterCheckString .= " if (UNLIKELY($parameterName < 0)) {\n";
1605 $parameterCheckString .= " ec = INDEX_SIZE_ERR;\n";
1606 $parameterCheckString .= " goto fail;\n";
1607 $parameterCheckString .= " }\n";
1612 return ($parameterCheckString, $paramIndex);
1615 sub GenerateConstructorCallback
1617 my $function = shift;
1618 my $dataNode = shift;
1619 my $implClassName = shift;
1621 my $raisesExceptions = @{$function->raisesExceptions};
1622 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1623 $raisesExceptions = 1;
1625 if (!$raisesExceptions) {
1626 foreach my $parameter (@{$function->parameters}) {
1627 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1628 $raisesExceptions = 1;
1633 my @beforeArgumentList;
1634 my @afterArgumentList;
1635 push(@implContent, <<END);
1636 v8::Handle<v8::Value> V8${implClassName}::constructorCallback(const v8::Arguments& args)
1638 INC_STATS("DOM.${implClassName}.Constructor");
1640 if (!args.IsConstructCall())
1641 return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError);
1643 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
1644 return args.Holder();
1647 push(@implContent, GenerateArgumentsCountCheck($function, $dataNode));
1649 if ($raisesExceptions) {
1650 AddToImplIncludes("ExceptionCode.h");
1651 push(@implContent, "\n");
1652 push(@implContent, " ExceptionCode ec = 0;\n");
1655 my ($parameterCheckString, $paramIndex) = GenerateParametersCheck($function, $implClassName);
1656 push(@implContent, $parameterCheckString);
1658 if ($dataNode->extendedAttributes->{"CallWith"} && $dataNode->extendedAttributes->{"CallWith"} eq "ScriptExecutionContext") {
1659 push(@beforeArgumentList, "context");
1660 push(@implContent, <<END);
1662 ScriptExecutionContext* context = getScriptExecutionContext();
1664 return throwError("${implClassName} constructor's associated context is not available", V8Proxy::ReferenceError);
1668 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1669 push(@afterArgumentList, "ec");
1674 foreach my $parameter (@{$function->parameters}) {
1675 last if $index eq $paramIndex;
1676 push(@argumentList, $parameter->name);
1680 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
1681 push(@implContent, "\n");
1682 push(@implContent, " RefPtr<${implClassName}> impl = ${implClassName}::create(${argumentString});\n");
1683 push(@implContent, " v8::Handle<v8::Object> wrapper = args.Holder();\n");
1685 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1686 push(@implContent, " if (ec)\n");
1687 push(@implContent, " goto fail;\n");
1690 my $DOMObject = "DOMObject";
1691 if (IsNodeSubType($dataNode)) {
1692 $DOMObject = "DOMNode";
1693 } elsif ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
1694 $DOMObject = "ActiveDOMObject";
1697 push(@implContent, <<END);
1699 V8DOMWrapper::setDOMWrapper(wrapper, &info, impl.get());
1701 V8DOMWrapper::setJSWrapperFor${DOMObject}(impl.get(), v8::Persistent<v8::Object>::New(wrapper));
1702 return args.Holder();
1705 if ($raisesExceptions) {
1706 push(@implContent, " fail:\n");
1707 push(@implContent, " return throwError(ec);\n");
1710 push(@implContent, "}\n");
1711 push(@implContent, "\n");
1714 sub GenerateEventConstructorCallback
1716 my $dataNode = shift;
1717 my $implClassName = shift;
1719 AddToImplIncludes("Dictionary.h");
1720 AddToImplIncludes("V8BindingMacros.h");
1721 push(@implContent, <<END);
1722 v8::Handle<v8::Value> V8${implClassName}::constructorCallback(const v8::Arguments& args)
1724 INC_STATS("DOM.${implClassName}.Constructor");
1726 if (!args.IsConstructCall())
1727 return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError);
1729 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
1730 return args.Holder();
1732 if (args.Length() < 1)
1733 return throwError("Not enough arguments", V8Proxy::TypeError);
1735 STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, type, args[0]);
1736 ${implClassName}Init eventInit;
1737 if (args.Length() >= 2) {
1738 EXCEPTION_BLOCK(Dictionary, options, args[1]);
1739 if (!fill${implClassName}Init(eventInit, options))
1740 return v8::Undefined();
1743 RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit);
1745 V8DOMWrapper::setDOMWrapper(args.Holder(), &info, event.get());
1746 return toV8(event.release(), args.Holder());
1749 bool fill${implClassName}Init(${implClassName}Init& eventInit, const Dictionary& options)
1753 foreach my $interfaceBase (@{$dataNode->parents}) {
1754 push(@implContent, <<END);
1755 if (!fill${interfaceBase}Init(eventInit, options))
1761 for (my $index = 0; $index < @{$dataNode->attributes}; $index++) {
1762 my $attribute = @{$dataNode->attributes}[$index];
1763 if ($attribute->signature->extendedAttributes->{"InitializedByEventConstructor"}) {
1764 my $attributeName = $attribute->signature->name;
1765 push(@implContent, " options.get(\"$attributeName\", eventInit.$attributeName);\n");
1769 push(@implContent, <<END);
1776 sub GenerateNamedConstructorCallback
1778 my $function = shift;
1779 my $dataNode = shift;
1780 my $implClassName = shift;
1782 my $raisesExceptions = @{$function->raisesExceptions};
1783 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1784 $raisesExceptions = 1;
1786 if (!$raisesExceptions) {
1787 foreach my $parameter (@{$function->parameters}) {
1788 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1789 $raisesExceptions = 1;
1794 my @beforeArgumentList;
1795 my @afterArgumentList;
1797 if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
1798 push(@implContent, <<END);
1799 WrapperTypeInfo V8${implClassName}Constructor::info = { V8${implClassName}Constructor::GetTemplate, V8${implClassName}::derefObject, V8${implClassName}::toActiveDOMObject, 0 };
1803 push(@implContent, <<END);
1804 WrapperTypeInfo V8${implClassName}Constructor::info = { V8${implClassName}Constructor::GetTemplate, 0, 0, 0 };
1809 push(@implContent, <<END);
1810 static v8::Handle<v8::Value> V8${implClassName}ConstructorCallback(const v8::Arguments& args)
1812 INC_STATS("DOM.${implClassName}.Constructor");
1814 if (!args.IsConstructCall())
1815 return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError);
1817 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
1818 return args.Holder();
1820 Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
1822 return throwError("${implClassName} constructor associated frame is unavailable", V8Proxy::ReferenceError);
1824 Document* document = frame->document();
1826 // Make sure the document is added to the DOM Node map. Otherwise, the ${implClassName} instance
1827 // may end up being the only node in the map and get garbage-collected prematurely.
1832 push(@implContent, GenerateArgumentsCountCheck($function, $dataNode));
1834 if ($raisesExceptions) {
1835 AddToImplIncludes("ExceptionCode.h");
1836 push(@implContent, "\n");
1837 push(@implContent, " ExceptionCode ec = 0;\n");
1840 my ($parameterCheckString, $paramIndex) = GenerateParametersCheck($function, $implClassName);
1841 push(@implContent, $parameterCheckString);
1843 push(@beforeArgumentList, "document");
1845 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1846 push(@afterArgumentList, "ec");
1851 foreach my $parameter (@{$function->parameters}) {
1852 last if $index eq $paramIndex;
1853 push(@argumentList, $parameter->name);
1857 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
1858 push(@implContent, "\n");
1859 push(@implContent, " RefPtr<${implClassName}> impl = ${implClassName}::createForJSConstructor(${argumentString});\n");
1860 push(@implContent, " v8::Handle<v8::Object> wrapper = args.Holder();\n");
1862 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1863 push(@implContent, " if (ec)\n");
1864 push(@implContent, " goto fail;\n");
1867 my $DOMObject = "DOMObject";
1868 # A DOMObject that is an ActiveDOMObject and also a DOMNode should be treated as an DOMNode here.
1869 # setJSWrapperForDOMNode() will look if node is active and choose correct map to add node to.
1870 if (IsNodeSubType($dataNode)) {
1871 $DOMObject = "DOMNode";
1872 } elsif ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
1873 $DOMObject = "ActiveDOMObject";
1875 push(@implContent, <<END);
1877 V8DOMWrapper::setDOMWrapper(wrapper, &V8${implClassName}Constructor::info, impl.get());
1879 V8DOMWrapper::setJSWrapperFor${DOMObject}(impl.get(), v8::Persistent<v8::Object>::New(wrapper));
1880 return args.Holder();
1883 if ($raisesExceptions) {
1884 push(@implContent, " fail:\n");
1885 push(@implContent, " return throwError(ec);\n");
1888 push(@implContent, "}\n");
1890 push(@implContent, <<END);
1892 v8::Persistent<v8::FunctionTemplate> V8${implClassName}Constructor::GetTemplate()
1894 static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
1895 if (!cachedTemplate.IsEmpty())
1896 return cachedTemplate;
1898 v8::HandleScope scope;
1899 v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8${implClassName}ConstructorCallback);
1901 v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
1902 instance->SetInternalFieldCount(V8${implClassName}::internalFieldCount);
1903 result->SetClassName(v8::String::New("${implClassName}"));
1904 result->Inherit(V8${implClassName}::GetTemplate());
1906 cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result);
1907 return cachedTemplate;
1913 sub GenerateBatchedAttributeData
1915 my $dataNode = shift;
1916 my $interfaceName = $dataNode->name;
1917 my $attributes = shift;
1919 foreach my $attribute (@$attributes) {
1920 my $conditionalString = GenerateConditionalString($attribute->signature);
1921 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
1922 GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
1923 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
1927 sub GenerateSingleBatchedAttribute
1929 my $interfaceName = shift;
1930 my $attribute = shift;
1931 my $delimiter = shift;
1933 my $attrName = $attribute->signature->name;
1934 my $attrExt = $attribute->signature->extendedAttributes;
1936 my $accessControl = "v8::DEFAULT";
1937 if ($attrExt->{"DoNotCheckSecurityOnGetter"}) {
1938 $accessControl = "v8::ALL_CAN_READ";
1939 } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) {
1940 $accessControl = "v8::ALL_CAN_WRITE";
1941 } elsif ($attrExt->{"DoNotCheckSecurity"}) {
1942 $accessControl = "v8::ALL_CAN_READ";
1943 if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
1944 $accessControl .= " | v8::ALL_CAN_WRITE";
1947 if ($attrExt->{"V8Unforgeable"}) {
1948 $accessControl .= " | v8::PROHIBITS_OVERWRITING";
1950 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
1952 my $customAccessor =
1953 $attrExt->{"Custom"} ||
1954 $attrExt->{"CustomSetter"} ||
1955 $attrExt->{"CustomGetter"} ||
1956 $attrExt->{"V8Custom"} ||
1957 $attrExt->{"V8CustomSetter"} ||
1958 $attrExt->{"V8CustomGetter"} ||
1960 if ($customAccessor eq "VALUE_IS_MISSING") {
1961 # use the naming convension, interface + (capitalize) attr name
1962 $customAccessor = $interfaceName . "::" . $attrName;
1967 my $propAttr = "v8::None";
1968 my $hasCustomSetter = 0;
1971 if ($attrExt->{"NotEnumerable"}) {
1972 $propAttr .= " | v8::DontEnum";
1974 if ($attrExt->{"V8Unforgeable"}) {
1975 $propAttr .= " | v8::DontDelete";
1978 my $on_proto = "0 /* on instance */";
1979 my $data = "0 /* no data */";
1982 if ($attribute->signature->type =~ /Constructor$/) {
1983 my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
1984 $constructorType =~ s/Constructor$//;
1985 # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
1986 # We do not generate the header file for NamedConstructor of class XXXX,
1987 # since we generate the NamedConstructor declaration into the header file of class XXXX.
1988 if ($constructorType !~ /Constructor$/ || $attribute->signature->extendedAttributes->{"V8CustomConstructor"} || $attribute->signature->extendedAttributes->{"CustomConstructor"}) {
1989 AddToImplIncludes("V8${constructorType}.h", $attribute->signature->extendedAttributes->{"Conditional"});
1991 if ($customAccessor) {
1992 $getter = "V8${customAccessor}AccessorGetter";
1994 $data = "&V8${constructorType}::info";
1995 $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
1998 $propAttr = "v8::ReadOnly";
2001 # Default Getter and Setter
2002 $getter = "${interfaceName}Internal::${attrName}AttrGetter";
2003 $setter = "${interfaceName}Internal::${attrName}AttrSetter";
2006 if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2007 $hasCustomSetter = 1;
2008 $setter = "V8${customAccessor}AccessorSetter";
2012 if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2013 $getter = "V8${customAccessor}AccessorGetter";
2018 if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
2020 # Handle the special case of window.top being marked as Replaceable.
2021 # FIXME: Investigate whether we could treat window.top as replaceable
2022 # and allow shadowing without it being a security hole.
2023 if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
2024 $propAttr .= " | v8::ReadOnly";
2028 # Read only attributes
2029 if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
2033 # An accessor can be installed on the proto
2034 if ($attrExt->{"V8OnProto"}) {
2035 $on_proto = "1 /* on proto */";
2038 my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
2039 "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2041 push(@implContent, $indent . " \/\/ $commentInfo\n");
2042 push(@implContent, $indent . " {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
2045 sub GenerateImplementationIndexer
2047 my $dataNode = shift;
2048 my $indexer = shift;
2049 my $interfaceName = $dataNode->name;
2051 # FIXME: Figure out what NumericIndexedGetter is really supposed to do. Right now, it's only set on WebGL-related files.
2052 my $hasCustomSetter = $dataNode->extendedAttributes->{"CustomIndexedSetter"} && !$dataNode->extendedAttributes->{"NumericIndexedGetter"};
2053 my $hasGetter = $dataNode->extendedAttributes->{"IndexedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
2055 # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
2056 if ($interfaceName eq "HTMLOptionsCollection") {
2060 # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
2061 # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
2062 # simplistic, mirrored indexer handling in addition to named property handling.
2063 my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
2064 if ($isSpecialCase) {
2066 if ($dataNode->extendedAttributes->{"CustomNamedSetter"}) {
2067 $hasCustomSetter = 1;
2075 AddToImplIncludes("V8Collection.h");
2078 $indexer = $codeGenerator->FindSuperMethod($dataNode, "item");
2081 my $indexerType = $indexer ? $indexer->type : 0;
2083 # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
2084 if ($interfaceName eq "WebKitCSSKeyframesRule") {
2085 $indexerType = "WebKitCSSKeyframeRule";
2088 if ($indexerType && !$hasCustomSetter) {
2089 if ($indexerType eq "DOMString") {
2090 my $conversion = $indexer->extendedAttributes->{"TreatReturnedNullStringAs"};
2091 if ($conversion && $conversion eq "Null") {
2092 push(@implContent, <<END);
2093 setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc);
2096 push(@implContent, <<END);
2097 setCollectionStringIndexedGetter<${interfaceName}>(desc);
2101 push(@implContent, <<END);
2102 setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
2104 # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
2105 AddToImplIncludes("V8${indexerType}.h");
2111 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
2112 my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
2113 my $setOn = "Instance";
2115 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2116 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2117 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2119 if ($interfaceName eq "DOMWindow") {
2120 $setOn = "Prototype";
2124 push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
2125 push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
2126 push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
2127 push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
2128 push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
2129 push(@implContent, ");\n");
2132 sub GenerateImplementationNamedPropertyGetter
2134 my $dataNode = shift;
2135 my $namedPropertyGetter = shift;
2136 my $interfaceName = $dataNode->name;
2137 my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"CustomNamedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
2139 # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
2140 # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
2141 if ($interfaceName eq "HTMLOptionsCollection") {
2142 $interfaceName = "HTMLCollection";
2143 $hasCustomNamedGetter = 1;
2146 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
2147 $hasCustomNamedGetter = 1;
2150 if ($interfaceName eq "HTMLDocument") {
2151 $hasCustomNamedGetter = 0;
2154 my $hasGetter = $dataNode->extendedAttributes->{"NamedGetter"} || $hasCustomNamedGetter;
2159 if (!$namedPropertyGetter) {
2160 $namedPropertyGetter = $codeGenerator->FindSuperMethod($dataNode, "namedItem");
2163 if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomNamedGetter) {
2164 AddToImplIncludes("V8Collection.h");
2165 my $type = $namedPropertyGetter->type;
2166 push(@implContent, <<END);
2167 setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
2172 my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"CustomNamedSetter"};
2173 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
2174 my $hasEnumerator = $dataNode->extendedAttributes->{"CustomEnumerateProperty"};
2175 my $setOn = "Instance";
2177 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2178 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2179 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2181 if ($interfaceName eq "DOMWindow") {
2182 $setOn = "Prototype";
2187 push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
2188 push(@implContent, $hasCustomNamedSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
2189 # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
2190 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyQuery, " : "0, ");
2191 push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
2192 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
2193 push(@implContent, ");\n");
2196 sub GenerateImplementationCustomCall
2198 my $dataNode = shift;
2199 my $interfaceName = $dataNode->name;
2200 my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
2202 if ($hasCustomCall) {
2203 push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
2207 sub GenerateImplementationMasqueradesAsUndefined
2209 my $dataNode = shift;
2210 if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
2212 push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n");
2216 sub IsTypedArrayType
2219 return 1 if (($type eq "ArrayBuffer") or ($type eq "ArrayBufferView"));
2220 return 1 if (($type eq "Uint8Array") or ($type eq "Uint8ClampedArray") or ($type eq "Uint16Array") or ($type eq "Uint32Array"));
2221 return 1 if (($type eq "Int8Array") or ($type eq "Int16Array") or ($type eq "Int32Array"));
2222 return 1 if (($type eq "Float32Array") or ($type eq "Float64Array"));
2227 sub GenerateImplementation
2230 my $dataNode = shift;
2231 my $interfaceName = $dataNode->name;
2232 my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($dataNode);
2233 my $className = "V8$interfaceName";
2234 my $implClassName = $interfaceName;
2236 # - Add default header template
2237 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2239 AddToImplIncludes("RuntimeEnabledFeatures.h");
2240 AddToImplIncludes("V8Proxy.h");
2241 AddToImplIncludes("V8Binding.h");
2242 AddToImplIncludes("V8BindingState.h");
2243 AddToImplIncludes("V8DOMWrapper.h");
2244 AddToImplIncludes("V8IsolatedContext.h");
2246 AddIncludesForType($interfaceName);
2248 my $toActive = $dataNode->extendedAttributes->{"ActiveDOMObject"} ? "${className}::toActiveDOMObject" : "0";
2250 # Find the super descriptor.
2251 my $parentClass = "";
2252 my $parentClassTemplate = "";
2253 foreach (@{$dataNode->parents}) {
2254 my $parent = $codeGenerator->StripModule($_);
2255 if ($parent eq "EventTarget") {
2258 AddToImplIncludes("V8${parent}.h");
2259 $parentClass = "V8" . $parent;
2260 $parentClassTemplate = $parentClass . "::GetTemplate()";
2263 push(@implContentDecls, "namespace WebCore {\n\n");
2264 my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
2265 push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive}, ${parentClassInfo} };\n\n");
2266 push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n");
2267 push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
2269 my $hasConstructors = 0;
2270 # Generate property accessors for attributes.
2271 for (my $index = 0; $index < @{$dataNode->attributes}; $index++) {
2272 my $attribute = @{$dataNode->attributes}[$index];
2273 my $attrType = $attribute->signature->type;
2275 # Generate special code for the constructor attributes.
2276 if ($attrType =~ /Constructor$/) {
2277 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2278 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2279 $hasConstructors = 1;
2284 if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
2285 $attribute->signature->extendedAttributes->{"V8OnProto"} = 1;
2288 if ($attrType eq "SerializedScriptValue") {
2289 AddToImplIncludes("SerializedScriptValue.h");
2292 # Do not generate accessor if this is a custom attribute. The
2293 # call will be forwarded to a hand-written accessor
2295 if ($attribute->signature->extendedAttributes->{"Custom"} ||
2296 $attribute->signature->extendedAttributes->{"V8Custom"}) {
2300 # Generate the accessor.
2301 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2302 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2303 GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
2305 if (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
2306 !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
2307 !$attribute->signature->extendedAttributes->{"Replaceable"} &&
2308 $attribute->type !~ /^readonly/ &&
2309 !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
2310 GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
2314 if ($hasConstructors) {
2315 GenerateConstructorGetter($dataNode, $implClassName);
2319 my $namedPropertyGetter;
2320 # Generate methods for functions.
2321 foreach my $function (@{$dataNode->functions}) {
2322 my $isCustom = $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"};
2324 GenerateFunctionCallback($function, $dataNode, $implClassName);
2325 if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
2326 GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName);
2330 if ($function->signature->name eq "item") {
2331 $indexer = $function->signature;
2334 if ($function->signature->name eq "namedItem") {
2335 $namedPropertyGetter = $function->signature;
2338 # If the function does not need domain security check, we need to
2339 # generate an access getter that returns different function objects
2340 # for different calling context.
2341 if (($dataNode->extendedAttributes->{"CheckSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2342 if (!$isCustom || $function->{overloadIndex} == 1) {
2343 GenerateDomainSafeFunctionGetter($function, $implClassName);
2349 my $attributes = $dataNode->attributes;
2351 # For the DOMWindow interface we partition the attributes into the
2352 # ones that disallows shadowing and the rest.
2353 my @disallowsShadowing;
2354 # Also separate out attributes that are enabled at runtime so we can process them specially.
2355 my @enabledAtRuntime;
2357 foreach my $attribute (@$attributes) {
2359 if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8Unforgeable"}) {
2360 push(@disallowsShadowing, $attribute);
2361 } elsif ($attribute->signature->extendedAttributes->{"V8EnabledAtRuntime"}) {
2362 push(@enabledAtRuntime, $attribute);
2364 push(@normal, $attribute);
2367 $attributes = \@normal;
2368 # Put the attributes that disallow shadowing on the shadow object.
2369 if (@disallowsShadowing) {
2370 push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n");
2371 GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
2372 push(@implContent, "};\n\n");
2375 my $has_attributes = 0;
2377 $has_attributes = 1;
2378 push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n");
2379 GenerateBatchedAttributeData($dataNode, $attributes);
2380 push(@implContent, "};\n\n");
2383 # Setup table of standard callback functions
2384 my $num_callbacks = 0;
2385 my $has_callbacks = 0;
2386 foreach my $function (@{$dataNode->functions}) {
2387 # Only one table entry is needed for overloaded methods:
2388 next if $function->{overloadIndex} > 1;
2390 my $attrExt = $function->signature->extendedAttributes;
2391 # Don't put any nonstandard functions into this table:
2392 if ($attrExt->{"V8Unforgeable"}) {
2395 if ($function->isStatic) {
2398 if ($attrExt->{"V8EnabledAtRuntime"} || RequiresCustomSignature($function) || $attrExt->{"V8DoNotCheckSignature"}) {
2401 if ($attrExt->{"DoNotCheckSecurity"} &&
2402 ($dataNode->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow")) {
2405 if ($attrExt->{"NotEnumerable"} || $attrExt->{"V8ReadOnly"}) {
2408 if (!$has_callbacks) {
2410 push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n");
2412 my $name = $function->signature->name;
2413 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2414 my $conditionalString = GenerateConditionalString($function->signature);
2415 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2416 push(@implContent, <<END);
2417 {"$name", $callback},
2419 push(@implContent, "#endif\n") if $conditionalString;
2422 push(@implContent, "};\n\n") if $has_callbacks;
2425 my $has_constants = 0;
2426 my @constantsEnabledAtRuntime;
2427 if (@{$dataNode->constants}) {
2429 push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n");
2431 foreach my $constant (@{$dataNode->constants}) {
2432 my $name = $constant->name;
2433 my $value = $constant->value;
2434 my $attrExt = $constant->extendedAttributes;
2435 my $conditional = $attrExt->{"Conditional"};
2436 my $implementedBy = $attrExt->{"ImplementedBy"};
2437 if ($implementedBy) {
2438 AddToImplIncludes("${implementedBy}.h");
2440 if ($attrExt->{"V8EnabledAtRuntime"}) {
2441 push(@constantsEnabledAtRuntime, $constant);
2443 # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
2444 # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we
2445 # handled this here, and converted it to a -1 constant in the c++ output.
2447 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2448 push(@implContent, "#if ${conditionalString}\n");
2450 push(@implContent, <<END);
2451 {"${name}", static_cast<signed int>($value)},
2453 push(@implContent, "#endif\n") if $conditional;
2456 if ($has_constants) {
2457 push(@implContent, "};\n\n");
2458 push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
2461 push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
2463 if ($dataNode->extendedAttributes->{"NamedConstructor"} && !($dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
2464 GenerateNamedConstructorCallback($dataNode->constructor, $dataNode, $interfaceName);
2465 } elsif ($dataNode->extendedAttributes->{"Constructor"} && !($dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
2466 GenerateConstructorCallback($dataNode->constructor, $dataNode, $interfaceName);
2467 } elsif (IsConstructorTemplate($dataNode, "Event")) {
2468 GenerateEventConstructorCallback($dataNode, $interfaceName);
2471 my $access_check = "";
2472 if ($dataNode->extendedAttributes->{"CheckSecurity"} && !($interfaceName eq "DOMWindow")) {
2473 $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));";
2476 # For the DOMWindow interface, generate the shadow object template
2477 # configuration method.
2478 if ($implClassName eq "DOMWindow") {
2479 push(@implContent, <<END);
2480 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
2482 batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs));
2484 // Install a security handler with V8.
2485 templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info));
2486 templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2492 if (!$parentClassTemplate) {
2493 $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
2496 # Generate the template configuration method
2497 push(@implContent, <<END);
2498 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc)
2500 desc->ReadOnlyPrototype();
2502 v8::Local<v8::Signature> defaultSignature;
2504 if ($dataNode->extendedAttributes->{"V8EnabledAtRuntime"}) {
2505 my $enable_function = GetRuntimeEnableFunctionName($dataNode);
2506 push(@implContent, <<END);
2507 if (!${enable_function}())
2508 defaultSignature = configureTemplate(desc, \"\", $parentClassTemplate, V8${interfaceName}::internalFieldCount, 0, 0, 0, 0);
2512 push(@implContent, <<END);
2513 defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount,
2515 # Set up our attributes if we have them
2516 if ($has_attributes) {
2517 push(@implContent, <<END);
2518 ${interfaceName}Attrs, WTF_ARRAY_LENGTH(${interfaceName}Attrs),
2521 push(@implContent, <<END);
2526 if ($has_callbacks) {
2527 push(@implContent, <<END);
2528 ${interfaceName}Callbacks, WTF_ARRAY_LENGTH(${interfaceName}Callbacks));
2531 push(@implContent, <<END);
2536 AddToImplIncludes("wtf/UnusedParam.h");
2537 push(@implContent, <<END);
2538 UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
2541 if (IsConstructable($dataNode)) {
2542 push(@implContent, <<END);
2543 desc->SetCallHandler(V8${interfaceName}::constructorCallback);
2547 if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) {
2548 push(@implContent, <<END);
2549 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
2550 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
2551 UNUSED_PARAM(instance); // In some cases, it will not be used.
2552 UNUSED_PARAM(proto); // In some cases, it will not be used.
2556 push(@implContent, " $access_check\n");
2558 # Setup the enable-at-runtime attrs if we have them
2559 foreach my $runtime_attr (@enabledAtRuntime) {
2560 my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
2561 my $conditionalString = GenerateConditionalString($runtime_attr->signature);
2562 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2563 push(@implContent, " if (${enable_function}()) {\n");
2564 push(@implContent, " static const BatchedAttribute attrData =\\\n");
2565 GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " ");
2566 push(@implContent, <<END);
2567 configureAttribute(instance, proto, attrData);
2570 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2573 # Setup the enable-at-runtime constants if we have them
2574 foreach my $runtime_const (@constantsEnabledAtRuntime) {
2575 my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
2576 my $conditionalString = GenerateConditionalString($runtime_const);
2577 my $name = $runtime_const->name;
2578 my $value = $runtime_const->value;
2579 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2580 push(@implContent, " if (${enable_function}()) {\n");
2581 push(@implContent, <<END);
2582 static const BatchedConstant constData = {"${name}", static_cast<signed int>(${value})};
2583 batchConfigureConstants(desc, proto, &constData, 1);
2585 push(@implContent, " }\n");
2586 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2589 GenerateImplementationIndexer($dataNode, $indexer);
2590 GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
2591 GenerateImplementationCustomCall($dataNode);
2592 GenerateImplementationMasqueradesAsUndefined($dataNode);
2594 # Define our functions with Set() or SetAccessor()
2595 my $total_functions = 0;
2596 foreach my $function (@{$dataNode->functions}) {
2597 # Only one accessor is needed for overloaded methods:
2598 next if $function->{overloadIndex} > 1;
2601 my $attrExt = $function->signature->extendedAttributes;
2602 my $name = $function->signature->name;
2604 my $property_attributes = "v8::DontDelete";
2605 if ($attrExt->{"NotEnumerable"}) {
2606 $property_attributes .= " | v8::DontEnum";
2608 if ($attrExt->{"V8ReadOnly"}) {
2609 $property_attributes .= " | v8::ReadOnly";
2612 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2614 my $template = "proto";
2615 if ($attrExt->{"V8Unforgeable"}) {
2616 $template = "instance";
2618 if ($function->isStatic) {
2622 my $conditional = "";
2623 if ($attrExt->{"V8EnabledAtRuntime"}) {
2624 # Only call Set()/SetAccessor() if this method should be enabled
2625 my $enable_function = GetRuntimeEnableFunctionName($function->signature);
2626 $conditional = "if (${enable_function}())\n ";
2629 if ($attrExt->{"DoNotCheckSecurity"} &&
2630 ($dataNode->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow")) {
2631 # Mark the accessor as ReadOnly and set it on the proto object so
2632 # it can be shadowed. This is really a hack to make it work.
2633 # There are several sceneria to call into the accessor:
2634 # 1) from the same domain: "window.open":
2635 # the accessor finds the DOM wrapper in the proto chain;
2636 # 2) from the same domain: "window.__proto__.open":
2637 # the accessor will NOT find a DOM wrapper in the prototype chain
2638 # 3) from another domain: "window.open":
2639 # the access find the DOM wrapper in the prototype chain
2640 # "window.__proto__.open" from another domain will fail when
2641 # accessing '__proto__'
2643 # The solution is very hacky and fragile, it really needs to be replaced
2644 # by a better solution.
2645 $property_attributes .= " | v8::ReadOnly";
2646 push(@implContent, <<END);
2649 ${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));
2655 my $signature = "defaultSignature";
2656 if ($attrExt->{"V8DoNotCheckSignature"} || $function->isStatic) {
2657 $signature = "v8::Local<v8::Signature>()";
2660 if (RequiresCustomSignature($function)) {
2661 $signature = "${name}Signature";
2662 push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function));
2665 # Normal function call is a template
2666 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2668 if ($property_attributes eq "v8::DontDelete") {
2669 $property_attributes = "";
2671 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2674 if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2675 # Standard type of callback, already created in the batch, so skip it here.
2679 my $conditionalString = GenerateConditionalString($function->signature);
2680 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2682 push(@implContent, <<END);
2683 ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);
2686 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2690 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
2692 if ($has_constants) {
2693 push(@implContent, <<END);
2694 batchConfigureConstants(desc, proto, ${interfaceName}Consts, WTF_ARRAY_LENGTH(${interfaceName}Consts));
2699 if ($interfaceName eq "DOMWindow") {
2700 push(@implContent, <<END);
2702 proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2703 desc->SetHiddenPrototype(true);
2704 instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2705 // Set access check callbacks, but turned off initially.
2706 // When a context is detached from a frame, turn on the access check.
2707 // Turning on checks also invalidates inline caches of the object.
2708 instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false);
2711 if ($interfaceName eq "HTMLDocument") {
2712 push(@implContent, <<END);
2713 desc->SetHiddenPrototype(true);
2716 if ($interfaceName eq "Location") {
2717 push(@implContent, <<END);
2719 // For security reasons, these functions are on the instance instead
2720 // of on the prototype object to ensure that they cannot be overwritten.
2721 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));
2722 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));
2723 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));
2727 my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
2728 push(@implContent, <<END);
2730 // Custom toString template
2731 desc->Set(getToStringName(), getToStringTemplate());
2735 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate()
2737 V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
2738 V8BindingPerIsolateData::TemplateMap::iterator result = data->rawTemplateMap().find(&info);
2739 if (result != data->rawTemplateMap().end())
2740 return result->second;
2742 v8::HandleScope handleScope;
2743 v8::Persistent<v8::FunctionTemplate> templ = createRawTemplate();
2744 data->rawTemplateMap().add(&info, templ);
2748 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()
2750 V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
2751 V8BindingPerIsolateData::TemplateMap::iterator result = data->templateMap().find(&info);
2752 if (result != data->templateMap().end())
2753 return result->second;
2755 v8::HandleScope handleScope;
2756 v8::Persistent<v8::FunctionTemplate> templ =
2757 Configure${className}Template(GetRawTemplate());
2758 data->templateMap().add(&info, templ);
2762 bool ${className}::HasInstance(v8::Handle<v8::Value> value)
2764 return GetRawTemplate()->HasInstance(value);
2769 if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
2770 # MessagePort is handled like an active dom object even though it doesn't inherit
2771 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
2772 my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
2773 push(@implContent, <<END);
2774 ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object)
2776 return ${returnValue};
2781 if ($implClassName eq "DOMWindow") {
2782 push(@implContent, <<END);
2783 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
2785 static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
2786 if (V8DOMWindowShadowObjectCache.IsEmpty()) {
2787 V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
2788 ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
2790 return V8DOMWindowShadowObjectCache;
2795 GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType);
2797 push(@implContent, <<END);
2799 void ${className}::derefObject(void* object)
2803 if (IsRefPtrType($interfaceName)) {
2804 push(@implContent, <<END);
2805 static_cast<${nativeType}*>(object)->deref();
2809 push(@implContent, <<END);
2812 } // namespace WebCore
2815 my $conditionalString = GenerateConditionalString($dataNode);
2816 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2818 # We've already added the header for this file in implFixedHeader, so remove
2819 # it from implIncludes to ensure we don't #include it twice.
2820 delete $implIncludes{"${className}.h"};
2823 sub GenerateHeaderContentHeader
2825 my $dataNode = shift;
2826 my $className = "V8" . $dataNode->name;
2827 my $conditionalString = GenerateConditionalString($dataNode);
2829 my @headerContentHeader = split("\r", $headerTemplate);
2831 push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
2832 push(@headerContentHeader, "\n#ifndef ${className}" . "_h");
2833 push(@headerContentHeader, "\n#define ${className}" . "_h\n\n");
2834 return @headerContentHeader;
2837 sub GenerateImplementationContentHeader
2839 my $dataNode = shift;
2840 my $className = "V8" . $dataNode->name;
2841 my $conditionalString = GenerateConditionalString($dataNode);
2843 my @implContentHeader = split("\r", $headerTemplate);
2845 push(@implContentHeader, "\n#include \"config.h\"\n");
2846 push(@implContentHeader, "#include \"${className}.h\"\n\n");
2847 push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
2848 return @implContentHeader;
2851 sub GenerateCallbackHeader
2854 my $dataNode = shift;
2856 my $interfaceName = $dataNode->name;
2857 my $className = "V8$interfaceName";
2860 # - Add default header template
2861 push(@headerContent, GenerateHeaderContentHeader($dataNode));
2863 my @unsortedIncludes = ();
2864 push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\"");
2865 push(@unsortedIncludes, "#include \"$interfaceName.h\"");
2866 push(@unsortedIncludes, "#include \"WorldContextHandle.h\"");
2867 push(@unsortedIncludes, "#include <v8.h>");
2868 push(@unsortedIncludes, "#include <wtf/Forward.h>");
2869 push(@headerContent, join("\n", sort @unsortedIncludes));
2871 push(@headerContent, "\n\nnamespace WebCore {\n\n");
2872 push(@headerContent, "class ScriptExecutionContext;\n\n");
2873 push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
2875 push(@headerContent, <<END);
2877 static PassRefPtr<${className}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
2879 ASSERT(value->IsObject());
2881 return adoptRef(new ${className}(value->ToObject(), context));
2884 virtual ~${className}();
2889 my $numFunctions = @{$dataNode->functions};
2890 if ($numFunctions > 0) {
2891 push(@headerContent, " // Functions\n");
2892 foreach my $function (@{$dataNode->functions}) {
2893 my @params = @{$function->parameters};
2894 if (!$function->signature->extendedAttributes->{"Custom"} &&
2895 !(GetNativeType($function->signature->type) eq "bool")) {
2896 push(@headerContent, " COMPILE_ASSERT(false)");
2899 push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
2902 foreach my $param (@params) {
2903 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2905 push(@headerContent, join(", ", @args));
2906 push(@headerContent, ");\n");
2910 push(@headerContent, <<END);
2913 ${className}(v8::Local<v8::Object>, ScriptExecutionContext*);
2915 v8::Persistent<v8::Object> m_callback;
2916 WorldContextHandle m_worldContext;
2921 push(@headerContent, "}\n\n");
2922 push(@headerContent, "#endif // $className" . "_h\n\n");
2924 my $conditionalString = GenerateConditionalString($dataNode);
2925 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
2928 sub GenerateCallbackImplementation
2931 my $dataNode = shift;
2932 my $interfaceName = $dataNode->name;
2933 my $className = "V8$interfaceName";
2935 # - Add default header template
2936 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2938 AddToImplIncludes("ScriptExecutionContext.h");
2939 AddToImplIncludes("V8Binding.h");
2940 AddToImplIncludes("V8CustomVoidCallback.h");
2941 AddToImplIncludes("V8Proxy.h");
2943 push(@implContent, "#include <wtf/Assertions.h>\n\n");
2944 push(@implContent, "namespace WebCore {\n\n");
2945 push(@implContent, <<END);
2946 ${className}::${className}(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
2947 : ActiveDOMCallback(context)
2948 , m_callback(v8::Persistent<v8::Object>::New(callback))
2949 , m_worldContext(UseCurrentWorld)
2953 ${className}::~${className}()
2955 m_callback.Dispose();
2961 my $numFunctions = @{$dataNode->functions};
2962 if ($numFunctions > 0) {
2963 push(@implContent, "// Functions\n");
2964 foreach my $function (@{$dataNode->functions}) {
2965 my @params = @{$function->parameters};
2966 if ($function->signature->extendedAttributes->{"Custom"} ||
2967 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
2971 AddIncludesForType($function->signature->type);
2972 push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(");
2975 foreach my $param (@params) {
2976 AddIncludesForType($param->type);
2977 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
2979 push(@implContent, join(", ", @args));
2981 push(@implContent, ")\n");
2982 push(@implContent, "{\n");
2983 push(@implContent, " if (!canInvokeCallback())\n");
2984 push(@implContent, " return true;\n\n");
2985 push(@implContent, " v8::HandleScope handleScope;\n\n");
2986 push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n");
2987 push(@implContent, " if (v8Context.IsEmpty())\n");
2988 push(@implContent, " return true;\n\n");
2989 push(@implContent, " v8::Context::Scope scope(v8Context);\n\n");
2992 foreach my $param (@params) {
2993 my $paramName = $param->name;
2994 push(@implContent, " v8::Handle<v8::Value> ${paramName}Handle = " . NativeToJSValue($param, $paramName) . ";\n");
2995 push(@implContent, " if (${paramName}Handle.IsEmpty()) {\n");
2996 push(@implContent, " if (!isScriptControllerTerminating())\n");
2997 push(@implContent, " CRASH();\n");
2998 push(@implContent, " return true;\n");
2999 push(@implContent, " }\n");
3000 push(@args, " ${paramName}Handle");
3003 if (scalar(@args) > 0) {
3004 push(@implContent, "\n v8::Handle<v8::Value> argv[] = {\n");
3005 push(@implContent, join(",\n", @args));
3006 push(@implContent, "\n };\n\n");
3008 push(@implContent, "\n v8::Handle<v8::Value> *argv = 0;\n\n");
3010 push(@implContent, " bool callbackReturnValue = false;\n");
3011 push(@implContent, " return !invokeCallback(m_callback, " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
3012 push(@implContent, "}\n");
3016 push(@implContent, "\n} // namespace WebCore\n\n");
3018 my $conditionalString = GenerateConditionalString($dataNode);
3019 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3022 sub GenerateToV8Converters
3024 my $dataNode = shift;
3025 my $interfaceName = shift;
3026 my $className = shift;
3027 my $nativeType = shift;
3029 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
3030 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
3031 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
3033 push(@implContent, <<END);
3035 v8::Handle<v8::Object> ${className}::wrapSlow(${nativeType}* impl)
3037 v8::Handle<v8::Object> wrapper;
3041 if (IsNodeSubType($dataNode)) {
3042 $proxyInit = "V8Proxy::retrieve(impl->document()->frame())";
3043 # DocumentType nodes are the only nodes that may have a NULL document.
3044 if ($interfaceName eq "DocumentType") {
3045 $proxyInit = "impl->document() ? $proxyInit : 0";
3050 push(@implContent, <<END);
3051 V8Proxy* proxy = $proxyInit;
3054 if (IsSubType($dataNode, "Document")) {
3055 push(@implContent, <<END);
3056 if (proxy && proxy->windowShell()->context().IsEmpty() && proxy->windowShell()->initContextIfNeeded()) {
3057 // initContextIfNeeded may have created a wrapper for the object, retry from the start.
3058 return ${className}::wrap(impl);
3063 # FIXME: We need a better way of recovering the correct prototype chain
3064 # for every sort of object. For now, we special-case cross-origin visible
3065 # objects (i.e., those with CheckSecurity).
3066 if (IsVisibleAcrossOrigins($dataNode)) {
3067 push(@implContent, <<END);
3068 if (impl->frame()) {
3069 proxy = V8Proxy::retrieve(impl->frame());
3071 proxy->windowShell()->initContextIfNeeded();
3076 if (IsNodeSubType($dataNode) || IsVisibleAcrossOrigins($dataNode)) {
3077 push(@implContent, <<END);
3079 v8::Handle<v8::Context> context;
3081 context = proxy->context();
3083 // Enter the node's context and create the wrapper in that context.
3084 if (!context.IsEmpty())
3089 push(@implContent, <<END);
3090 wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl);
3092 if (IsNodeSubType($dataNode) || IsVisibleAcrossOrigins($dataNode)) {
3093 push(@implContent, <<END);
3094 // Exit the node's context if it was entered.
3095 if (!context.IsEmpty())
3100 push(@implContent, <<END);
3101 if (UNLIKELY(wrapper.IsEmpty()))
3104 push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName);
3106 push(@implContent, <<END);
3107 v8::Persistent<v8::Object> wrapperHandle = v8::Persistent<v8::Object>::New(wrapper);
3109 if (!hasDependentLifetime)
3110 wrapperHandle.MarkIndependent();
3112 if (IsNodeSubType($dataNode)) {
3113 push(@implContent, <<END);
3114 wrapperHandle.SetWrapperClassId(v8DOMSubtreeClassId);
3117 push(@implContent, <<END);
3118 ${domMapFunction}.set(impl, wrapperHandle);
3121 push(@implContent, <<END);
3127 sub GetDomMapFunction
3129 my $dataNode = shift;
3131 return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
3132 return "getActiveDOMNodeMap()" if (IsNodeSubType($dataNode) && $dataNode->extendedAttributes->{"ActiveDOMObject"});
3133 return "getDOMNodeMap()" if (IsNodeSubType($dataNode));
3134 return "getActiveDOMObjectMap()" if $dataNode->extendedAttributes->{"ActiveDOMObject"};
3135 return "getDOMObjectMap()";
3138 sub GetNativeTypeForConversions
3140 my $dataNode = shift;
3143 $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->IsSVGTypeNeedingTearOff($type);
3147 sub GenerateFunctionCallString()
3149 my $function = shift;
3150 my $numberOfParameters = shift;
3152 my $implClassName = shift;
3154 my $name = $function->signature->name;
3155 my $returnType = GetTypeFromSignature($function->signature);
3156 my $nativeReturnType = GetNativeType($returnType, 0);
3159 my $isSVGTearOffType = ($codeGenerator->IsSVGTypeNeedingTearOff($returnType) and not $implClassName =~ /List$/);
3160 $nativeReturnType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType;
3162 if ($function->signature->extendedAttributes->{"ImplementedAs"}) {
3163 $name = $function->signature->extendedAttributes->{"ImplementedAs"};
3167 my $hasScriptState = 0;
3171 my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
3172 if ($implementedBy) {
3173 AddToImplIncludes("${implementedBy}.h");
3174 unshift(@arguments, "imp") if !$function->isStatic;
3175 $functionName = "${implementedBy}::${name}";
3176 } elsif ($function->isStatic) {
3177 $functionName = "${implClassName}::${name}";
3179 $functionName = "imp->${name}";
3182 my $callWith = $function->signature->extendedAttributes->{"CallWith"};
3183 my @callWithOutput = ();
3184 my @callWithArgs = GenerateCallWith($callWith, \@callWithOutput, $indent, 0, 1, $function);
3185 $result .= join("", @callWithOutput);
3186 push(@arguments, @callWithArgs);
3187 $index += @callWithArgs;
3188 $numberOfParameters += @callWithArgs;
3190 foreach my $parameter (@{$function->parameters}) {
3191 if ($index eq $numberOfParameters) {
3194 my $paramName = $parameter->name;
3195 my $paramType = $parameter->type;
3197 if ($parameter->type eq "IDBKey" || $parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
3198 push @arguments, "$paramName.get()";
3199 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($parameter->type) and not $implClassName =~ /List$/) {
3200 push @arguments, "$paramName->propertyReference()";
3201 $result .= $indent . "if (!$paramName) {\n";
3202 $result .= $indent . " V8Proxy::setDOMException(WebCore::TYPE_MISMATCH_ERR);\n";
3203 $result .= $indent . " return v8::Handle<v8::Value>();\n";
3204 $result .= $indent . "}\n";
3205 } elsif ($parameter->type eq "SVGMatrix" and $implClassName eq "SVGTransformList") {
3206 push @arguments, "$paramName.get()";
3208 push @arguments, $paramName;
3213 if (@{$function->raisesExceptions}) {