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->SkipIncludeHeader($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 NeedsToVisitDOMWrapper
186 my $dataNode = shift;
187 return GetGenerateIsReachable($dataNode) || GetCustomIsReachable($dataNode);
190 sub GetGenerateIsReachable
192 my $dataNode = shift;
193 return $dataNode->extendedAttributes->{"GenerateIsReachable"} || $dataNode->extendedAttributes->{"V8GenerateIsReachable"} || ""
196 sub GetCustomIsReachable
198 my $dataNode = shift;
199 return $dataNode->extendedAttributes->{"CustomIsReachable"} || $dataNode->extendedAttributes->{"V8CustomIsReachable"};
202 sub GenerateVisitDOMWrapper
204 my ($dataNode, $implClassName) = @_;
206 if (GetCustomIsReachable($dataNode)) {
210 push(@implContent, <<END);
211 void V8${implClassName}::visitDOMWrapper(DOMDataStore* store, void* object, v8::Persistent<v8::Object> wrapper)
213 ${implClassName}* impl = static_cast<${implClassName}*>(object);
215 if (GetGenerateIsReachable($dataNode) eq "ImplElementRoot" ||
216 GetGenerateIsReachable($dataNode) eq "ImplOwnerRoot" ||
217 GetGenerateIsReachable($dataNode) eq "ImplOwnerNodeRoot" ||
218 GetGenerateIsReachable($dataNode) eq "ImplBaseRoot") {
221 $methodName = "element" if (GetGenerateIsReachable($dataNode) eq "ImplElementRoot");
222 $methodName = "owner" if (GetGenerateIsReachable($dataNode) eq "ImplOwnerRoot");
223 $methodName = "ownerNode" if (GetGenerateIsReachable($dataNode) eq "ImplOwnerNodeRoot");
224 $methodName = "base" if (GetGenerateIsReachable($dataNode) eq "ImplBaseRoot");
226 push(@implContent, <<END);
227 if (Node* owner = impl->${methodName}()) {
228 v8::Persistent<v8::Object> ownerWrapper = store->domNodeMap().get(owner);
229 if (!ownerWrapper.IsEmpty()) {
230 v8::Persistent<v8::Value> value = wrapper;
231 v8::V8::AddImplicitReferences(ownerWrapper, &value, 1);
237 push(@implContent, <<END);
243 sub GetSVGPropertyTypes
245 my $implType = shift;
248 my $svgListPropertyType;
251 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
253 $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
254 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
256 # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType>
257 $svgNativeType = "$svgNativeType ";
259 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
260 if ($svgNativeType =~ /SVGPropertyTearOff/) {
261 $svgPropertyType = $svgWrappedNativeType;
262 AddToImplIncludes("SVGAnimatedPropertyTearOff.h");
263 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
264 $svgListPropertyType = $svgWrappedNativeType;
265 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
266 $headerIncludes{"SVGStaticListPropertyTearOff.h"} = 1;
267 } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
268 $svgListPropertyType = $svgWrappedNativeType;
269 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
270 $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
271 } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
272 $svgListPropertyType = $svgWrappedNativeType;
273 $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
276 if ($svgPropertyType) {
277 $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint";
280 return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
286 my $dataNode = shift;
288 my $interfaceName = $dataNode->name;
289 my $className = "V8$interfaceName";
290 my $implClassName = $interfaceName;
292 # Copy contents of parent classes except the first parent or if it is
294 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
295 $codeGenerator->LinkOverloadedFunctions($dataNode);
297 my $hasDependentLifetime = $dataNode->extendedAttributes->{"V8DependentLifetime"} || $dataNode->extendedAttributes->{"ActiveDOMObject"}
298 || GetGenerateIsReachable($dataNode) || $className =~ /SVG/;
299 if (!$hasDependentLifetime) {
300 foreach (@{$dataNode->parents}) {
301 my $parent = $codeGenerator->StripModule($_);
302 next if $parent eq "EventTarget";
303 $headerIncludes{"V8${parent}.h"} = 1;
307 # - Add default header template
308 push(@headerContent, GenerateHeaderContentHeader($dataNode));
310 $headerIncludes{"wtf/text/StringHash.h"} = 1;
311 $headerIncludes{"WrapperTypeInfo.h"} = 1;
312 $headerIncludes{"V8Binding.h"} = 1;
313 $headerIncludes{"V8DOMWrapper.h"} = 1;
314 $headerIncludes{"wtf/HashMap.h"} = 1;
315 $headerIncludes{"v8.h"} = 1;
317 my $headerClassInclude = GetHeaderClassInclude($implClassName);
318 $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
320 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
322 foreach my $headerInclude (sort keys(%headerIncludes)) {
323 if ($headerInclude =~ /wtf|v8\.h/) {
324 push(@headerContent, "#include \<${headerInclude}\>\n");
326 push(@headerContent, "#include \"${headerInclude}\"\n");
330 push(@headerContent, "\nnamespace WebCore {\n");
331 push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
332 if ($svgNativeType) {
333 if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
334 push(@headerContent, "\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
336 push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
340 push(@headerContent, "\n");
341 push(@headerContent, "class FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect";
342 push(@headerContent, "class Dictionary;\n") if IsConstructorTemplate($dataNode, "Event");
344 my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
345 if ($dataNode->extendedAttributes->{"NamedConstructor"}) {
346 push(@headerContent, <<END);
347 class V8${nativeType}Constructor {
349 static v8::Persistent<v8::FunctionTemplate> GetTemplate();
350 static WrapperTypeInfo info;
356 push(@headerContent, "class $className {\n");
357 push(@headerContent, "public:\n");
359 push(@headerContent, " static const bool hasDependentLifetime = ");
360 if ($hasDependentLifetime) {
361 push(@headerContent, "true;\n");
362 } elsif (@{$dataNode->parents}) {
363 # Even if this type doesn't have the V8DependentLifetime attribute its parents may.
364 # Let the compiler statically determine this for us.
366 foreach (@{$dataNode->parents}) {
367 my $parent = $codeGenerator->StripModule($_);
368 next if $parent eq "EventTarget";
369 $headerIncludes{"V8${parent}.h"} = 1;
370 push(@headerContent, "${separator}V8${parent}::hasDependentLifetime");
373 push(@headerContent, ";\n");
375 push(@headerContent, "false;\n");
378 my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
379 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
380 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
382 push(@headerContent, <<END);
383 static bool HasInstance(v8::Handle<v8::Value>);
384 static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
385 static v8::Persistent<v8::FunctionTemplate> GetTemplate();
386 static ${nativeType}* toNative(v8::Handle<v8::Object> object)
388 return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
390 inline static v8::Handle<v8::Object> wrap(${nativeType}*, v8::Isolate* = 0${forceNewObjectParameter});
391 static void derefObject(void*);
392 static void visitDOMWrapper(DOMDataStore*, void*, v8::Persistent<v8::Object>);
393 static WrapperTypeInfo info;
395 if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
396 push(@headerContent, " static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
399 if ($implClassName eq "DOMWindow") {
400 push(@headerContent, <<END);
401 static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate();
405 if ($implClassName eq "HTMLDocument") {
406 push(@headerContent, <<END);
407 static v8::Local<v8::Object> WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl);
408 static v8::Handle<v8::Value> GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key, v8::Isolate*);
412 my @enabledPerContext;
413 foreach my $function (@{$dataNode->functions}) {
414 my $name = $function->signature->name;
415 my $attrExt = $function->signature->extendedAttributes;
417 if (($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) && !$attrExt->{"ImplementedBy"} && $function->{overloadIndex} == 1) {
418 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
419 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
420 push(@headerContent, <<END);
421 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&);
423 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
425 if ($attrExt->{"V8EnabledPerContext"}) {
426 push(@enabledPerContext, $function);
430 if (IsConstructable($dataNode)) {
431 push(@headerContent, <<END);
432 static v8::Handle<v8::Value> constructorCallback(const v8::Arguments&);
436 foreach my $attribute (@{$dataNode->attributes}) {
437 my $name = $attribute->signature->name;
438 my $attrExt = $attribute->signature->extendedAttributes;
439 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
440 if (($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"} ||
441 $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) &&
442 !$attrExt->{"ImplementedBy"}) {
443 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
444 push(@headerContent, <<END);
445 static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);
447 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
449 if (($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"} ||
450 $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) &&
451 !$attrExt->{"ImplementedBy"}) {
452 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
453 push(@headerContent, <<END);
454 static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);
456 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
458 if ($attrExt->{"V8EnabledPerContext"}) {
459 push(@enabledPerContext, $attribute);
463 GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode);
464 GenerateHeaderCustomCall($dataNode);
465 GenerateHeaderCustomInternalFieldIndices($dataNode);
467 if ($dataNode->extendedAttributes->{"CheckSecurity"}) {
468 push(@headerContent, <<END);
469 static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
470 static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
474 if (@enabledPerContext) {
475 push(@headerContent, <<END);
476 static void installPerContextProperties(v8::Handle<v8::Object>, ${implClassName}*);
480 my $wrapSlowArgumentType = GetPassRefPtrType($nativeType);
481 push(@headerContent, <<END);
483 static v8::Handle<v8::Object> wrapSlow(${wrapSlowArgumentType}, v8::Isolate*);
488 push(@headerContent, <<END);
489 v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl, v8::Isolate* isolate${forceNewObjectInput})
492 push(@headerContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
493 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName, "isolate");
494 my $getCachedWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getCachedWrapper(impl)" : "${domMapFunction}.get(impl)";
495 push(@headerContent, <<END);
496 v8::Handle<v8::Object> wrapper = $getCachedWrapper;
497 if (!wrapper.IsEmpty())
500 push(@headerContent, " }\n") if IsDOMNodeType($interfaceName);
501 push(@headerContent, <<END);
502 return ${className}::wrapSlow(impl, isolate);
506 if ($interfaceName eq 'Element' or $dataNode->extendedAttributes->{"SuppressToJSObject"}) {
507 # Do not generate toV8() for performance optimization.
508 } elsif (!($dataNode->extendedAttributes->{"CustomToJSObject"} or $dataNode->extendedAttributes->{"V8CustomToJSObject"})) {
509 push(@headerContent, <<END);
511 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Isolate* isolate = 0${forceNewObjectParameter})
514 return v8NullWithCheck(isolate);
515 return ${className}::wrap(impl, isolate${forceNewObjectCall});
518 } elsif ($interfaceName ne 'Node') {
519 push(@headerContent, <<END);
521 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Isolate* = 0${forceNewObjectParameter});
524 push(@headerContent, <<END);
526 v8::Handle<v8::Value> toV8Slow(Node*, v8::Isolate*, bool);
528 inline v8::Handle<v8::Value> toV8(Node* impl, v8::Isolate* isolate = 0, bool forceNewObject = false)
531 return v8NullWithCheck(isolate);
532 if (UNLIKELY(forceNewObject))
533 return toV8Slow(impl, isolate, forceNewObject);
534 v8::Handle<v8::Value> wrapper = V8DOMWrapper::getCachedWrapper(impl);
535 if (!wrapper.IsEmpty())
537 return toV8Slow(impl, isolate, false);
542 push(@headerContent, <<END);
543 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl, v8::Isolate* isolate = 0${forceNewObjectParameter})
545 return toV8(impl.get(), isolate${forceNewObjectCall});
549 if (IsConstructorTemplate($dataNode, "Event")) {
550 push(@headerContent, "\nbool fill${implClassName}Init(${implClassName}Init&, const Dictionary&);\n");
553 push(@headerContent, "\n}\n\n");
554 push(@headerContent, "#endif // $className" . "_h\n");
556 my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
557 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
560 sub GetInternalFields
562 my $dataNode = shift;
563 my $name = $dataNode->name;
565 my @customInternalFields = ();
566 # We can't ask whether a parent type has a given extendedAttribute,
567 # so special-case AbstractWorker and WorkerContext to include all sub-types.
568 # Event listeners on DOM nodes are explicitly supported in the GC controller.
569 # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't.
570 # FIXME: Simplify this when all EventTargets are subtypes of EventTarget.
571 if (!IsNodeSubType($dataNode)
572 && ($dataNode->extendedAttributes->{"EventTarget"}
573 || $dataNode->extendedAttributes->{"IsWorkerContext"}
574 || IsSubType($dataNode, "AbstractWorker")
575 || $name eq "SVGElementInstance"
576 || $name eq "EventTarget")) {
577 push(@customInternalFields, "eventListenerCacheIndex");
580 if ($name eq "DOMWindow") {
581 push(@customInternalFields, "enteredIsolatedWorldIndex");
583 return @customInternalFields;
586 sub GetHeaderClassInclude
588 my $className = shift;
589 if ($className =~ /SVGPathSeg/) {
590 $className =~ s/Abs|Rel//;
592 return "wtf/${className}.h" if IsTypedArrayType($className);
593 return "" if ($codeGenerator->SkipIncludeHeader($className));
594 return "${className}.h";
597 sub GenerateHeaderCustomInternalFieldIndices
599 my $dataNode = shift;
600 my @customInternalFields = GetInternalFields($dataNode);
601 my $customFieldCounter = 0;
602 foreach my $customInternalField (@customInternalFields) {
603 push(@headerContent, <<END);
604 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
606 $customFieldCounter++;
608 push(@headerContent, <<END);
609 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
613 my %indexerSpecialCases = (
615 "HTMLAppletElement" => 1,
616 "HTMLEmbedElement" => 1,
617 "HTMLObjectElement" => 1
620 sub GenerateHeaderNamedAndIndexedPropertyAccessors
622 my $dataNode = shift;
623 my $interfaceName = $dataNode->name;
624 my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"IndexedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
625 my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"CustomIndexedSetter"} && !$dataNode->extendedAttributes->{"NumericIndexedGetter"};
626 my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"NamedGetter"} || $dataNode->extendedAttributes->{"CustomNamedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
627 my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"CustomNamedSetter"};
628 my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
629 my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomEnumerateProperty"};
630 if ($interfaceName eq "HTMLOptionsCollection") {
631 $interfaceName = "HTMLCollection";
632 $hasCustomIndexedGetter = 1;
633 $hasCustomNamedGetter = 1;
635 if ($interfaceName eq "DOMWindow") {
636 $hasCustomDeleters = 0;
637 $hasCustomEnumerator = 0;
639 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
640 $hasCustomNamedGetter = 1;
642 if ($interfaceName eq "HTMLDocument") {
643 $hasCustomNamedGetter = 0;
644 $hasCustomIndexedGetter = 0;
646 my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
648 if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
649 push(@headerContent, <<END);
650 static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
654 if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
655 push(@headerContent, <<END);
656 static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
659 if ($hasCustomDeleters) {
660 push(@headerContent, <<END);
661 static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
664 if ($hasCustomNamedGetter) {
665 push(@headerContent, <<END);
666 static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
669 if ($hasCustomNamedSetter) {
670 push(@headerContent, <<END);
671 static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
674 if ($hasCustomDeleters) {
675 push(@headerContent, <<END);
676 static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
679 if ($hasCustomEnumerator) {
680 push(@headerContent, <<END);
681 static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
682 static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
687 sub GenerateHeaderCustomCall
689 my $dataNode = shift;
691 if ($dataNode->extendedAttributes->{"CustomCall"}) {
692 push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
694 if ($dataNode->name eq "Event") {
695 push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
696 push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);\n");
698 if ($dataNode->name eq "Location") {
699 push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
700 push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
701 push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
707 my $dataNode = shift;
708 my $parentType = shift;
709 return 1 if ($dataNode->name eq $parentType);
710 foreach (@allParents) {
711 my $parent = $codeGenerator->StripModule($_);
712 return 1 if $parent eq $parentType;
719 my $dataNode = shift;
720 return IsSubType($dataNode, "Node");
723 sub IsVisibleAcrossOrigins
725 my $dataNode = shift;
726 return $dataNode->extendedAttributes->{"CheckSecurity"} && !($dataNode->name eq "DOMWindow");
731 my $dataNode = shift;
733 return $dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"Constructor"} || $dataNode->extendedAttributes->{"ConstructorTemplate"};
736 sub IsConstructorTemplate
738 my $dataNode = shift;
739 my $template = shift;
741 return $dataNode->extendedAttributes->{"ConstructorTemplate"} && $dataNode->extendedAttributes->{"ConstructorTemplate"} eq $template;
744 sub GenerateDomainSafeFunctionGetter
746 my $function = shift;
747 my $implClassName = shift;
749 my $className = "V8" . $implClassName;
750 my $funcName = $function->signature->name;
752 my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())";
753 if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
754 $signature = "v8::Local<v8::Signature>()";
757 my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature);
759 push(@implContentDecls, <<END);
760 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
762 INC_STATS(\"DOM.$implClassName.$funcName._get\");
763 static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
764 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This());
765 if (holder.IsEmpty()) {
766 // can only reach here by 'object.__proto__.func', and it should passed
767 // domain security check already
768 return privateTemplate->GetFunction();
770 ${implClassName}* imp = ${className}::toNative(holder);
771 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
772 static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
773 return sharedTemplate->GetFunction();
775 return privateTemplate->GetFunction();
781 sub GenerateConstructorGetter
783 my $dataNode = shift;
784 my $implClassName = shift;
786 push(@implContentDecls, <<END);
787 static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
789 INC_STATS(\"DOM.$implClassName.constructors._get\");
790 v8::Handle<v8::Value> data = info.Data();
791 ASSERT(data->IsExternal() || data->IsNumber());
792 WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data);
795 if ($implClassName eq "DOMWindow") {
796 push(@implContentDecls, <<END);
797 // Get the proxy corresponding to the DOMWindow if possible to
798 // make sure that the constructor function is constructed in the
799 // context of the DOMWindow and not in the context of the caller.
800 return V8DOMWrapper::constructorForType(type, V8DOMWindow::toNative(info.Holder()));
802 } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
803 push(@implContentDecls, <<END);
804 return V8DOMWrapper::constructorForType(type, V8WorkerContext::toNative(info.Holder()));
807 push(@implContentDecls, " return v8::Handle<v8::Value>();");
810 push(@implContentDecls, <<END);
816 sub GenerateFeatureObservation
818 my $measureAs = shift;
821 AddToImplIncludes("FeatureObserver.h");
822 return " FeatureObserver::observe(activeDOMWindow(BindingState::instance()), FeatureObserver::${measureAs});\n";
828 sub GenerateNormalAttrGetter
830 my $attribute = shift;
831 my $dataNode = shift;
832 my $implClassName = shift;
833 my $interfaceName = shift;
835 my $attrExt = $attribute->signature->extendedAttributes;
836 my $attrName = $attribute->signature->name;
837 my $attrType = GetTypeFromSignature($attribute->signature);
838 $codeGenerator->AssertNotSequenceType($attrType);
839 my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
841 my $getterStringUsesImp = $implClassName ne "SVGNumber";
842 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
845 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
846 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
848 push(@implContentDecls, <<END);
849 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
851 INC_STATS("DOM.$implClassName.$attrName._get");
853 push(@implContentDecls, GenerateFeatureObservation($attrExt->{"V8MeasureAs"}));
855 if ($svgNativeType) {
856 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
857 if ($svgWrappedNativeType =~ /List/) {
858 push(@implContentDecls, <<END);
859 $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
862 push(@implContentDecls, <<END);
863 $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());
864 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
866 if ($getterStringUsesImp) {
867 push(@implContentDecls, <<END);
868 $svgWrappedNativeType* imp = &impInstance;
872 } elsif ($attrExt->{"V8OnProto"} || $attrExt->{"V8Unforgeable"}) {
873 if ($interfaceName eq "DOMWindow") {
874 push(@implContentDecls, <<END);
875 v8::Handle<v8::Object> holder = info.Holder();
878 # perform lookup first
879 push(@implContentDecls, <<END);
880 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This());
881 if (holder.IsEmpty())
882 return v8::Handle<v8::Value>();
885 push(@implContentDecls, <<END);
886 ${implClassName}* imp = V8${implClassName}::toNative(holder);
889 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
890 my $url = $attribute->signature->extendedAttributes->{"URL"};
891 if ($getterStringUsesImp && $reflect && !$url && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
892 # Generate super-compact call for regular attribute getter:
893 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
894 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
895 AddToImplIncludes("${namespace}.h");
896 push(@implContentDecls, " Element* imp = V8Element::toNative(info.Holder());\n");
897 push(@implContentDecls, " return v8ExternalString(imp->getAttribute(${namespace}::${contentAttributeName}Attr), info.GetIsolate());\n");
898 push(@implContentDecls, "}\n\n");
899 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
901 # Skip the rest of the function!
903 if ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
904 push(@implContentDecls, <<END);
905 v8::Handle<v8::String> propertyName = v8::String::NewSymbol("${attrName}");
906 v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(propertyName);
907 if (!value.IsEmpty())
911 if (!$attribute->isStatic) {
912 push(@implContentDecls, <<END);
913 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
918 # Generate security checks if necessary
919 if ($attribute->signature->extendedAttributes->{"CheckSecurityForNode"}) {
920 push(@implContentDecls, " if (!V8BindingSecurity::shouldAllowAccessToNode(V8BindingState::Only(), imp->" . $attribute->signature->name . "()))\n return v8::Handle<v8::Value>(v8::Null(info.GetIsolate()));\n\n");
923 my $useExceptions = 1 if @{$attribute->getterExceptions};
924 if ($useExceptions) {
925 AddToImplIncludes("ExceptionCode.h");
926 push(@implContentDecls, " ExceptionCode ec = 0;\n");
929 my $returnType = GetTypeFromSignature($attribute->signature);
932 if ($getterStringUsesImp) {
933 my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
934 push(@arguments, "ec") if $useExceptions;
935 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
936 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
937 AddToImplIncludes("${implementedBy}.h");
938 unshift(@arguments, "imp") if !$attribute->isStatic;
939 $functionName = "${implementedBy}::${functionName}";
940 } elsif ($attribute->isStatic) {
941 $functionName = "${implClassName}::${functionName}";
943 $functionName = "imp->${functionName}";
945 unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentDecls, " ", 0, 0));
946 $getterString = "${functionName}(" . join(", ", @arguments) . ")";
948 $getterString = "impInstance";
954 if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
955 push(@implContentDecls, " if (!imp->document())\n");
956 push(@implContentDecls, " return v8::Handle<v8::Value>();\n");
959 if ($useExceptions) {
960 if ($nativeType =~ /^V8Parameter/) {
961 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $getterString) . ";\n");
963 push(@implContentDecls, " $nativeType v = $getterString;\n");
965 push(@implContentDecls, " if (UNLIKELY(ec))\n");
966 push(@implContentDecls, " return V8Proxy::setDOMException(ec, info.GetIsolate());\n");
968 if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
969 push(@implContentDecls, " if (state.hadException())\n");
970 push(@implContentDecls, " return throwError(state.exception(), info.GetIsolate());\n");
974 $result .= ".release()" if (IsRefPtrType($returnType));
976 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
977 $result = $getterString;
978 # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
979 $result = "static_pointer_cast<SVGAnimatedEnumeration>($result)" if $returnType eq "SVGAnimatedEnumeration";
982 # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
983 # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
984 # the newly created wrapper into an internal field of the holder object.
985 if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"})
986 && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow"
987 && $returnType ne "MessagePortArray"
988 && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) {
990 my $arrayType = $codeGenerator->GetArrayType($returnType);
992 if (!$codeGenerator->SkipIncludeHeader($arrayType)) {
993 AddToImplIncludes("V8$arrayType.h");
994 AddToImplIncludes("$arrayType.h");
996 push(@implContentDecls, " return v8Array(${getterString}, info.GetIsolate());\n");
997 push(@implContentDecls, "}\n\n");
1001 AddIncludesForType($returnType);
1002 # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
1003 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
1004 push(@implContentDecls, " RefPtr<$returnType> result = ${getterString};\n");
1005 my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName, "info.GetIsolate()");
1006 push(@implContentDecls, " v8::Handle<v8::Value> wrapper = result.get() ? ${domMapFunction}.get(result.get()) : v8::Handle<v8::Object>();\n");
1007 push(@implContentDecls, " if (wrapper.IsEmpty()) {\n");
1008 push(@implContentDecls, " wrapper = toV8(result.get(), info.GetIsolate());\n");
1009 push(@implContentDecls, " if (!wrapper.IsEmpty())\n");
1010 if ($dataNode->name eq "DOMWindow") {
1011 push(@implContentDecls, " V8DOMWrapper::setNamedHiddenWindowReference(imp->frame(), \"${attrName}\", wrapper);\n");
1013 push(@implContentDecls, " V8DOMWrapper::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n");
1015 push(@implContentDecls, " }\n");
1016 push(@implContentDecls, " return wrapper;\n");
1017 push(@implContentDecls, "}\n\n");
1018 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1022 if (($codeGenerator->IsSVGAnimatedType($implClassName) or $implClassName eq "SVGViewSpec") and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) {
1023 AddToImplIncludes("V8$attrType.h");
1024 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
1025 # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
1026 push(@implContentDecls, " return toV8(static_cast<$svgNativeType*>($result), info.GetIsolate());\n");
1027 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $implClassName =~ /List$/) {
1028 AddToImplIncludes("V8$attrType.h");
1029 AddToImplIncludes("SVGPropertyTearOff.h");
1030 my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
1031 if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
1032 my $getter = $result;
1033 $getter =~ s/imp->//;
1034 $getter =~ s/\(\)//;
1036 my $updateMethod = "&${implClassName}::update" . $codeGenerator->WK_ucfirst($getter);
1038 my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($implClassName);
1039 if ($selfIsTearOffType) {
1040 AddToImplIncludes("SVGStaticPropertyWithParentTearOff.h");
1041 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$implClassName, /;
1043 if ($result =~ /matrix/ and $implClassName eq "SVGTransform") {
1044 # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
1045 # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
1046 $result =~ s/matrix/svgMatrix/;
1049 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(wrapper, $result, $updateMethod)), info.GetIsolate());\n");
1051 AddToImplIncludes("SVGStaticPropertyTearOff.h");
1052 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
1054 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(imp, $result, $updateMethod)), info.GetIsolate());\n");
1056 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
1057 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create(imp, $result)), info.GetIsolate());\n");
1058 } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
1059 push(@implContentDecls, " return toV8(WTF::getPtr($result), info.GetIsolate());\n");
1061 push(@implContentDecls, " return toV8(WTF::getPtr(${tearOffType}::create($result)), info.GetIsolate());\n");
1063 } elsif ($attribute->signature->type eq "MessagePortArray") {
1064 AddToImplIncludes("MessagePort.h");
1065 AddToImplIncludes("V8MessagePort.h");
1066 my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
1067 push(@implContentDecls, <<END);
1068 MessagePortArray* ports = imp->${getterFunc}();
1070 return v8::Array::New(0);
1071 MessagePortArray portsCopy(*ports);
1072 v8::Local<v8::Array> portArray = v8::Array::New(portsCopy.size());
1073 for (size_t i = 0; i < portsCopy.size(); ++i)
1074 portArray->Set(v8Integer(i, info.GetIsolate()), toV8(portsCopy[i].get(), info.GetIsolate()));
1078 if ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
1079 my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
1080 push(@implContentDecls, <<END);
1081 SerializedScriptValue* serialized = imp->${getterFunc}();
1082 value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::Null(info.GetIsolate()));
1083 info.Holder()->SetHiddenValue(propertyName, value);
1087 push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, "info.GetIsolate()").";\n");
1091 push(@implContentDecls, "}\n\n"); # end of getter
1092 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1095 sub GenerateReplaceableAttrSetter
1097 my $dataNode = shift;
1098 my $implClassName = shift;
1100 push(@implContentDecls, <<END);
1101 static void ${implClassName}ReplaceableAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
1103 INC_STATS("DOM.$implClassName.replaceable._set");
1105 push(@implContentDecls, GenerateFeatureObservation($dataNode->extendedAttributes->{"V8MeasureAs"}));
1107 if ($implClassName eq "DOMWindow" || $dataNode->extendedAttributes->{"CheckSecurity"}) {
1108 push(@implContentDecls, <<END);
1109 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
1110 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
1115 push(@implContentDecls, <<END);
1116 info.This()->ForceSet(name, value);
1122 sub GenerateNormalAttrSetter
1124 my $attribute = shift;
1125 my $dataNode = shift;
1126 my $implClassName = shift;
1127 my $interfaceName = shift;
1129 AddToImplIncludes("V8BindingMacros.h");
1131 my $attrName = $attribute->signature->name;
1132 my $attrExt = $attribute->signature->extendedAttributes;
1134 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1135 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1137 push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n");
1138 push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
1139 push(@implContentDecls, GenerateFeatureObservation($attribute->signature->extendedAttributes->{"V8MeasureAs"}));
1141 # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
1142 # interface type, then if the incoming value does not implement that interface, a TypeError is
1143 # thrown rather than silently passing NULL to the C++ code.
1144 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
1145 # strings and numbers, so do not throw TypeError if the attribute is of these types.
1146 if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
1147 my $argType = GetTypeFromSignature($attribute->signature);
1148 if (IsWrapperType($argType)) {
1149 push(@implContentDecls, " if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value)) {\n");
1150 push(@implContentDecls, " V8Proxy::throwTypeError(0, info.GetIsolate());\n");
1151 push(@implContentDecls, " return;\n");
1152 push(@implContentDecls, " }\n");
1156 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implClassName);
1157 if ($svgNativeType) {
1158 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1159 if ($svgWrappedNativeType =~ /List$/) {
1160 push(@implContentDecls, <<END);
1161 $svgNativeType* imp = V8${implClassName}::toNative(info.Holder());
1164 AddToImplIncludes("ExceptionCode.h");
1165 push(@implContentDecls, " $svgNativeType* wrapper = V8${implClassName}::toNative(info.Holder());\n");
1166 push(@implContentDecls, " if (wrapper->isReadOnly()) {\n");
1167 push(@implContentDecls, " V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR, info.GetIsolate());\n");
1168 push(@implContentDecls, " return;\n");
1169 push(@implContentDecls, " }\n");
1170 push(@implContentDecls, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1171 push(@implContentDecls, " $svgWrappedNativeType* imp = &impInstance;\n");
1173 } elsif ($attrExt->{"V8OnProto"}) {
1174 push(@implContentDecls, <<END);
1175 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
1178 my $attrType = GetTypeFromSignature($attribute->signature);
1179 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1180 if ($reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) {
1181 # Generate super-compact call for regular attribute setter:
1182 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
1183 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1184 AddToImplIncludes("${namespace}.h");
1185 push(@implContentDecls, " Element* imp = V8Element::toNative(info.Holder());\n");
1186 push(@implContentDecls, " AtomicString v = toAtomicWebCoreStringWithNullCheck(value);\n");
1187 push(@implContentDecls, " imp->setAttribute(${namespace}::${contentAttributeName}Attr, v);\n");
1188 push(@implContentDecls, "}\n\n");
1189 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1191 # Skip the rest of the function!
1194 if (!$attribute->isStatic) {
1195 push(@implContentDecls, <<END);
1196 ${implClassName}* imp = V8${implClassName}::toNative(info.Holder());
1201 my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
1202 if ($attribute->signature->type eq "EventListener") {
1203 if ($dataNode->name eq "DOMWindow") {
1204 push(@implContentDecls, " if (!imp->document())\n");
1205 push(@implContentDecls, " return;\n");
1208 my $value = JSValueToNative($attribute->signature, "value", "info.GetIsolate()");
1209 my $arrayType = $codeGenerator->GetArrayType($nativeType);
1211 if ($nativeType =~ /^V8Parameter/) {
1212 push(@implContentDecls, " " . ConvertToV8Parameter($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
1213 } elsif ($arrayType) {
1214 push(@implContentDecls, " Vector<$arrayType> v = $value;\n");
1216 push(@implContentDecls, " $nativeType v = $value;\n");
1221 my $returnType = GetTypeFromSignature($attribute->signature);
1222 if (IsRefPtrType($returnType) && !$codeGenerator->GetArrayType($returnType)) {
1223 $result = "WTF::getPtr(" . $result . ")";
1226 my $useExceptions = 1 if @{$attribute->setterExceptions};
1228 if ($useExceptions) {
1229 AddToImplIncludes("ExceptionCode.h");
1230 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1233 if ($implClassName eq "SVGNumber") {
1234 push(@implContentDecls, " *imp = $result;\n");
1236 if ($attribute->signature->type eq "EventListener") {
1237 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
1238 AddToImplIncludes("V8AbstractEventListener.h");
1239 if (!IsNodeSubType($dataNode)) {
1240 push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n");
1242 if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
1243 AddToImplIncludes("V8EventListenerList.h");
1244 AddToImplIncludes("V8WorkerContextErrorHandler.h");
1245 push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
1246 } elsif ($interfaceName eq "DOMWindow" and $attribute->signature->name eq "onerror") {
1247 AddToImplIncludes("V8EventListenerList.h");
1248 AddToImplIncludes("V8WindowErrorHandler.h");
1249 push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WindowErrorHandler>(value, true)");
1251 push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)");
1253 push(@implContentDecls, ", ec") if $useExceptions;
1254 push(@implContentDecls, ");\n");
1256 my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute);
1257 push(@arguments, $result);
1258 push(@arguments, "ec") if $useExceptions;
1259 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
1260 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
1261 AddToImplIncludes("${implementedBy}.h");
1262 unshift(@arguments, "imp") if !$attribute->isStatic;
1263 $functionName = "${implementedBy}::${functionName}";
1264 } elsif ($attribute->isStatic) {
1265 $functionName = "${interfaceName}::${functionName}";
1267 $functionName = "imp->${functionName}";
1269 unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentDecls, " ", 1, 0));
1270 push(@implContentDecls, " ${functionName}(" . join(", ", @arguments) . ");\n");
1274 if ($useExceptions) {
1275 push(@implContentDecls, " if (UNLIKELY(ec))\n");
1276 push(@implContentDecls, " V8Proxy::setDOMException(ec, info.GetIsolate());\n");
1279 if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
1280 push(@implContentDecls, " if (state.hadException())\n");
1281 push(@implContentDecls, " throwError(state.exception(), info.GetIsolate());\n");
1284 if ($svgNativeType) {
1285 if ($useExceptions) {
1286 push(@implContentDecls, " if (!ec)\n");
1287 push(@implContentDecls, " wrapper->commitChange();\n");
1289 push(@implContentDecls, " wrapper->commitChange();\n");
1293 if ($attribute->signature->type eq "SerializedScriptValue" && $attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1294 push(@implContentDecls, <<END);
1295 info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // Invalidate the cached value.
1299 push(@implContentDecls, " return;\n");
1300 push(@implContentDecls, "}\n\n"); # end of setter
1301 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1304 sub GetFunctionTemplateCallbackName
1306 my $function = shift;
1307 my $interfaceName = shift;
1309 my $name = $function->signature->name;
1311 if ($function->signature->extendedAttributes->{"Custom"} ||
1312 $function->signature->extendedAttributes->{"V8Custom"}) {
1313 if ($function->signature->extendedAttributes->{"Custom"} &&
1314 $function->signature->extendedAttributes->{"V8Custom"}) {
1315 die "Custom and V8Custom should be mutually exclusive!"
1317 return "V8${interfaceName}::${name}Callback";
1319 return "${interfaceName}V8Internal::${name}Callback";
1323 sub GenerateNewFunctionTemplate
1325 my $function = shift;
1326 my $interfaceName = shift;
1327 my $signature = shift;
1329 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
1330 return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)";
1333 sub GenerateEventListenerCallback
1335 my $implClassName = shift;
1336 my $requiresHiddenDependency = shift;
1337 my $functionName = shift;
1338 my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only";
1339 my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()";
1340 my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove";
1342 push(@implContentDecls, <<END);
1343 static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args)
1345 INC_STATS("DOM.${implClassName}.${functionName}EventListener()");
1346 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType});
1348 V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue());
1350 if ($requiresHiddenDependency) {
1351 push(@implContentDecls, <<END);
1352 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex);
1355 push(@implContentDecls, <<END);
1357 return v8::Undefined();
1363 sub GenerateParametersCheckExpression
1365 my $numParameters = shift;
1366 my $function = shift;
1368 my @andExpression = ();
1369 push(@andExpression, "args.Length() == $numParameters");
1370 my $parameterIndex = 0;
1371 foreach my $parameter (@{$function->parameters}) {
1372 last if $parameterIndex >= $numParameters;
1373 my $value = "args[$parameterIndex]";
1374 my $type = GetTypeFromSignature($parameter);
1376 # Only DOMString or wrapper types are checked.
1377 # For DOMString, Null, Undefined and any Object are accepted too, as
1378 # these are acceptable values for a DOMString argument (any Object can
1379 # be converted to a string via .toString).
1380 if ($codeGenerator->IsStringType($type)) {
1381 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
1382 } elsif ($parameter->extendedAttributes->{"Callback"}) {
1383 # For Callbacks only checks if the value is null or object.
1384 push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction())");
1385 } elsif (IsArrayType($type) || $codeGenerator->GetSequenceType($type)) {
1386 # FIXME: Add proper support for T[], T[]?, sequence<T>.
1387 if ($parameter->isNullable) {
1388 push(@andExpression, "(${value}->IsNull() || ${value}->IsArray())");
1390 push(@andExpression, "(${value}->IsArray())");
1392 } elsif (IsWrapperType($type)) {
1393 if ($parameter->isNullable) {
1394 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))");
1396 push(@andExpression, "(V8${type}::HasInstance($value))");
1402 my $res = join(" && ", @andExpression);
1403 $res = "($res)" if @andExpression > 1;
1407 sub GenerateFunctionParametersCheck
1409 my $function = shift;
1411 my @orExpression = ();
1412 my $numParameters = 0;
1413 foreach my $parameter (@{$function->parameters}) {
1414 if ($parameter->extendedAttributes->{"Optional"}) {
1415 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1419 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1420 return join(" || ", @orExpression);
1423 sub GenerateOverloadedFunctionCallback
1425 my $function = shift;
1426 my $dataNode = shift;
1427 my $implClassName = shift;
1429 # Generate code for choosing the correct overload to call. Overloads are
1430 # chosen based on the total number of arguments passed and the type of
1431 # values passed in non-primitive argument slots. When more than a single
1432 # overload is applicable, precedence is given according to the order of
1433 # declaration in the IDL.
1435 my $name = $function->signature->name;
1436 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1437 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1438 push(@implContentDecls, <<END);
1439 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1441 INC_STATS(\"DOM.$implClassName.$name\");
1443 push(@implContentDecls, GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"}));
1445 foreach my $overload (@{$function->{overloads}}) {
1446 my $parametersCheck = GenerateFunctionParametersCheck($overload);
1447 push(@implContentDecls, " if ($parametersCheck)\n");
1448 push(@implContentDecls, " return ${name}$overload->{overloadIndex}Callback(args);\n");
1450 push(@implContentDecls, <<END);
1451 return V8Proxy::throwTypeError(0, args.GetIsolate());
1453 push(@implContentDecls, "}\n\n");
1454 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1457 sub GenerateFunctionCallback
1459 my $function = shift;
1460 my $dataNode = shift;
1461 my $implClassName = shift;
1463 my $interfaceName = $dataNode->name;
1464 my $name = $function->signature->name;
1466 if (@{$function->{overloads}} > 1) {
1467 # Append a number to an overloaded method's name to make it unique:
1468 $name = $name . $function->{overloadIndex};
1471 # Adding and removing event listeners are not standard callback behavior,
1472 # but they are extremely consistent across the various classes that take event listeners,
1473 # so we can generate them as a "special case".
1474 if ($name eq "addEventListener") {
1475 GenerateEventListenerCallback($implClassName, !IsNodeSubType($dataNode), "add");
1477 } elsif ($name eq "removeEventListener") {
1478 GenerateEventListenerCallback($implClassName, !IsNodeSubType($dataNode), "remove");
1482 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1483 push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString;
1484 push(@implContentDecls, <<END);
1485 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)
1487 INC_STATS(\"DOM.$implClassName.$name\");
1489 push(@implContentDecls, GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"}));
1491 push(@implContentDecls, GenerateArgumentsCountCheck($function, $dataNode));
1493 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implClassName);
1495 if ($svgNativeType) {
1496 my $nativeClassName = GetNativeType($implClassName);
1497 if ($implClassName =~ /List$/) {
1498 push(@implContentDecls, " $nativeClassName imp = V8${implClassName}::toNative(args.Holder());\n");
1500 AddToImplIncludes("ExceptionCode.h");
1501 push(@implContentDecls, " $nativeClassName wrapper = V8${implClassName}::toNative(args.Holder());\n");
1502 push(@implContentDecls, " if (wrapper->isReadOnly())\n");
1503 push(@implContentDecls, " return V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR, args.GetIsolate());\n");
1504 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implClassName);
1505 push(@implContentDecls, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1506 push(@implContentDecls, " $svgWrappedNativeType* imp = &impInstance;\n");
1508 } elsif (!$function->isStatic) {
1509 push(@implContentDecls, <<END);
1510 ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
1514 # Check domain security if needed
1515 if (($dataNode->extendedAttributes->{"CheckSecurity"}
1516 || $interfaceName eq "DOMWindow")
1517 && !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
1518 # We have not find real use cases yet.
1519 push(@implContentDecls, <<END);
1520 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
1521 return v8::Handle<v8::Value>();
1525 my $raisesExceptions = @{$function->raisesExceptions};
1526 if (!$raisesExceptions) {
1527 foreach my $parameter (@{$function->parameters}) {
1528 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1529 $raisesExceptions = 1;
1534 if ($raisesExceptions) {
1535 AddToImplIncludes("ExceptionCode.h");
1536 push(@implContentDecls, " ExceptionCode ec = 0;\n");
1537 push(@implContentDecls, " {\n");
1538 # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1539 # of objects (like Strings) declared later, causing compile errors. The block scope ends
1540 # right before the label 'fail:'.
1543 if ($function->signature->extendedAttributes->{"CheckSecurityForNode"}) {
1544 push(@implContentDecls, " if (!V8BindingSecurity::shouldAllowAccessToNode(V8BindingState::Only(), imp->" . $function->signature->name . "(ec)))\n");
1545 push(@implContentDecls, " return v8::Handle<v8::Value>(v8::Null(args.GetIsolate()));\n");
1549 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $implClassName);
1550 push(@implContentDecls, $parameterCheckString);
1552 # Build the function call string.
1553 push(@implContentDecls, GenerateFunctionCallString($function, $paramIndex, " ", $implClassName, %replacements));
1555 if ($raisesExceptions) {
1556 push(@implContentDecls, " }\n");
1557 push(@implContentDecls, " fail:\n");
1558 push(@implContentDecls, " return V8Proxy::setDOMException(ec, args.GetIsolate());\n");
1561 push(@implContentDecls, "}\n\n");
1562 push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
1565 sub GenerateCallWith
1567 my $callWith = shift;
1568 return () unless $callWith;
1569 my $outputArray = shift;
1571 my $returnVoid = shift;
1572 my $emptyContext = shift;
1573 my $function = shift;
1576 if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) {
1577 if ($emptyContext) {
1578 push(@$outputArray, $indent . "EmptyScriptState state;\n");
1579 push(@callWithArgs, "&state");
1581 push(@$outputArray, $indent . "ScriptState* state = ScriptState::current();\n");
1582 push(@$outputArray, $indent . "if (!state)\n");
1583 push(@$outputArray, $indent . " return" . ($returnVoid ? "" : " v8::Undefined()") . ";\n");
1584 push(@callWithArgs, "state");
1587 if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptExecutionContext")) {
1588 push(@$outputArray, $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n");
1589 push(@$outputArray, $indent . "if (!scriptContext)\n");
1590 push(@$outputArray, $indent . " return" . ($returnVoid ? "" : " v8::Undefined()") . ";\n");
1591 push(@callWithArgs, "scriptContext");
1593 if ($function and $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments")) {
1594 push(@$outputArray, $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, " . @{$function->parameters} . "));\n");
1595 push(@callWithArgs, "scriptArguments");
1596 AddToImplIncludes("ScriptArguments.h");
1598 if ($codeGenerator->ExtendedAttributeContains($callWith, "CallStack")) {
1599 push(@$outputArray, $indent . "RefPtr<ScriptCallStack> callStack(createScriptCallStackForInspector());\n");
1600 push(@$outputArray, $indent . "if (!callStack)\n");
1601 push(@$outputArray, $indent . " return v8::Undefined();\n");
1602 push(@callWithArgs, "callStack");
1603 AddToImplIncludes("ScriptCallStack.h");
1604 AddToImplIncludes("ScriptCallStackFactory.h");
1606 return @callWithArgs;
1609 sub GenerateArgumentsCountCheck
1611 my $function = shift;
1612 my $dataNode = shift;
1614 my $numMandatoryParams = 0;
1615 my $optionalSeen = 0;
1616 foreach my $param (@{$function->parameters}) {
1617 if ($param->extendedAttributes->{"Optional"}) {
1620 die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if $optionalSeen;
1621 $numMandatoryParams++;
1625 my $argumentsCountCheckString = "";
1626 if ($numMandatoryParams >= 1) {
1627 $argumentsCountCheckString .= " if (args.Length() < $numMandatoryParams)\n";
1628 $argumentsCountCheckString .= " return V8Proxy::throwNotEnoughArgumentsError(args.GetIsolate());\n";
1630 return $argumentsCountCheckString;
1635 my $paramName = shift;
1638 foreach my $param (@paramList) {
1639 if ($paramName eq $param) {
1647 sub GenerateParametersCheck
1649 my $function = shift;
1650 my $implClassName = shift;
1652 my $parameterCheckString = "";
1654 my @paramTransferListNames = ();
1655 my %replacements = ();
1657 foreach my $parameter (@{$function->parameters}) {
1658 TranslateParameter($parameter);
1660 my $parameterName = $parameter->name;
1662 # Optional arguments with [Optional] should generate an early call with fewer arguments.
1663 # Optional arguments with [Optional=...] should not generate the early call.
1664 my $optional = $parameter->extendedAttributes->{"Optional"};
1665 if ($optional && $optional ne "DefaultIsUndefined" && $optional ne "DefaultIsNullString" && !$parameter->extendedAttributes->{"Callback"}) {
1666 $parameterCheckString .= " if (args.Length() <= $paramIndex) {\n";
1667 my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName, %replacements);
1668 $parameterCheckString .= $functionCall;
1669 $parameterCheckString .= " }\n";
1672 my $parameterDefaultPolicy = "DefaultIsUndefined";
1673 if ($optional and $optional eq "DefaultIsNullString") {
1674 $parameterDefaultPolicy = "DefaultIsNullString";
1677 if (GetIndexOf($parameterName, @paramTransferListNames) != -1) {
1678 $replacements{$parameterName} = "messagePortArray" . ucfirst($parameterName);
1683 AddToImplIncludes("ExceptionCode.h");
1684 my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1685 if ($parameter->extendedAttributes->{"Callback"}) {
1686 my $className = GetCallbackClassName($parameter->type);
1687 AddToImplIncludes("$className.h");
1689 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $parameterName;\n";
1690 $parameterCheckString .= " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n";
1691 $parameterCheckString .= " if (!args[$paramIndex]->IsFunction())\n";
1692 $parameterCheckString .= " return throwError(TYPE_MISMATCH_ERR, args.GetIsolate());\n";
1693 $parameterCheckString .= " $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n";
1694 $parameterCheckString .= " }\n";
1696 $parameterCheckString .= " if (args.Length() <= $paramIndex || !args[$paramIndex]->IsFunction())\n";
1697 $parameterCheckString .= " return throwError(TYPE_MISMATCH_ERR, args.GetIsolate());\n";
1698 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $parameterName = ${className}::create(args[$paramIndex], getScriptExecutionContext());\n";
1700 } elsif ($parameter->extendedAttributes->{"Clamp"}) {
1701 my $nativeValue = "${parameterName}NativeValue";
1702 my $paramType = $parameter->type;
1703 $parameterCheckString .= " $paramType $parameterName = 0\n";
1704 $parameterCheckString .= " EXCEPTION_BLOCK(double, $nativeValue, args[$paramIndex]->NumberValue());\n";
1705 $parameterCheckString .= " if (!isnan($nativeValue))\n";
1706 $parameterCheckString .= " $parameterName = clampTo<$paramType>($nativeValue);\n";
1707 } elsif ($parameter->type eq "SerializedScriptValue") {
1708 AddToImplIncludes("SerializedScriptValue.h");
1709 my $useTransferList = 0;
1710 my $transferListName = "";
1711 my $TransferListName = "";
1712 if ($parameter->extendedAttributes->{"TransferList"}) {
1713 $transferListName = $parameter->extendedAttributes->{"TransferList"};
1714 push(@paramTransferListNames, $transferListName);
1716 my @allParameterNames = ();
1717 foreach my $parameter (@{$function->parameters}) {
1718 push(@allParameterNames, $parameter->name);
1720 my $transferListIndex = GetIndexOf($transferListName, @allParameterNames);
1721 if ($transferListIndex == -1) {
1722 die "IDL error: TransferList refers to a nonexistent argument";
1725 AddToImplIncludes("wtf/ArrayBuffer.h");
1726 AddToImplIncludes("MessagePort.h");
1727 $TransferListName = ucfirst($transferListName);
1728 $parameterCheckString .= " MessagePortArray messagePortArray$TransferListName;\n";
1729 $parameterCheckString .= " ArrayBufferArray arrayBufferArray$TransferListName;\n";
1730 $parameterCheckString .= " if (args.Length() > $transferListIndex) {\n";
1731 $parameterCheckString .= " if (!extractTransferables(args[$transferListIndex], messagePortArray$TransferListName, arrayBufferArray$TransferListName))\n";
1732 $parameterCheckString .= " return V8Proxy::throwTypeError(\"Could not extract transferables\");\n";
1733 $parameterCheckString .= " }\n";
1734 $useTransferList = 1;
1736 $parameterCheckString .= " bool ${parameterName}DidThrow = false;\n";
1737 if (!$useTransferList) {
1738 $parameterCheckString .= " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow, args.GetIsolate());\n";
1740 $parameterCheckString .= " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], &messagePortArray$TransferListName, &arrayBufferArray$TransferListName, ${parameterName}DidThrow, args.GetIsolate());\n";
1742 $parameterCheckString .= " if (${parameterName}DidThrow)\n";
1743 $parameterCheckString .= " return v8::Undefined();\n";
1744 } elsif (TypeCanFailConversion($parameter)) {
1745 $parameterCheckString .= " $nativeType $parameterName = " .
1746 JSValueToNative($parameter, "args[$paramIndex]", "args.GetIsolate()") . ";\n";
1747 $parameterCheckString .= " if (UNLIKELY(!$parameterName)) {\n";
1748 $parameterCheckString .= " ec = TYPE_MISMATCH_ERR;\n";
1749 $parameterCheckString .= " goto fail;\n";
1750 $parameterCheckString .= " }\n";
1751 } elsif ($nativeType =~ /^V8Parameter/) {
1752 my $value = JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterDefaultPolicy)", "args.GetIsolate()");
1753 $parameterCheckString .= " " . ConvertToV8Parameter($parameter, $nativeType, $parameterName, $value) . "\n";
1755 AddToImplIncludes("V8BindingMacros.h");
1756 # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
1757 # interface type, then if the incoming value does not implement that interface, a TypeError
1758 # is thrown rather than silently passing NULL to the C++ code.
1759 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
1760 # to both strings and numbers, so do not throw TypeError if the argument is of these
1762 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1763 my $argValue = "args[$paramIndex]";
1764 my $argType = GetTypeFromSignature($parameter);
1765 if (IsWrapperType($argType)) {
1766 $parameterCheckString .= " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue))\n";
1767 $parameterCheckString .= " return V8Proxy::throwTypeError(0, args.GetIsolate());\n";
1770 $parameterCheckString .= " EXCEPTION_BLOCK($nativeType, $parameterName, " .
1771 JSValueToNative($parameter, "MAYBE_MISSING_PARAMETER(args, $paramIndex, $parameterDefaultPolicy)", "args.GetIsolate()") . ");\n";
1772 if ($nativeType eq 'Dictionary') {
1773 $parameterCheckString .= " if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject())\n";
1774 $parameterCheckString .= " return V8Proxy::throwTypeError(\"Not an object.\", args.GetIsolate());\n";
1778 if ($parameter->extendedAttributes->{"IsIndex"}) {
1779 $parameterCheckString .= " if (UNLIKELY($parameterName < 0)) {\n";
1780 $parameterCheckString .= " ec = INDEX_SIZE_ERR;\n";
1781 $parameterCheckString .= " goto fail;\n";
1782 $parameterCheckString .= " }\n";
1787 return ($parameterCheckString, $paramIndex, %replacements);
1790 sub GenerateConstructorCallback
1792 my $function = shift;
1793 my $dataNode = shift;
1794 my $implClassName = shift;
1796 my $raisesExceptions = @{$function->raisesExceptions};
1797 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1798 $raisesExceptions = 1;
1800 if (!$raisesExceptions) {
1801 foreach my $parameter (@{$function->parameters}) {
1802 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1803 $raisesExceptions = 1;
1808 my $maybeObserveFeature = GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"});
1810 my @beforeArgumentList;
1811 my @afterArgumentList;
1812 push(@implContent, <<END);
1813 v8::Handle<v8::Value> V8${implClassName}::constructorCallback(const v8::Arguments& args)
1815 INC_STATS("DOM.${implClassName}.Constructor");
1816 ${maybeObserveFeature}
1817 if (!args.IsConstructCall())
1818 return V8Proxy::throwTypeError("DOM object constructor cannot be called as a function.");
1820 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
1821 return args.Holder();
1824 push(@implContent, GenerateArgumentsCountCheck($function, $dataNode));
1826 if ($raisesExceptions) {
1827 AddToImplIncludes("ExceptionCode.h");
1828 push(@implContent, "\n");
1829 push(@implContent, " ExceptionCode ec = 0;\n");
1832 # FIXME: Currently [Constructor(...)] does not yet support [Optional] arguments.
1833 # It just supports [Optional=DefaultIsUndefined] or [Optional=DefaultIsNullString].
1834 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $implClassName);
1835 push(@implContent, $parameterCheckString);
1837 if ($dataNode->extendedAttributes->{"CallWith"} && $dataNode->extendedAttributes->{"CallWith"} eq "ScriptExecutionContext") {
1838 push(@beforeArgumentList, "context");
1839 push(@implContent, <<END);
1841 ScriptExecutionContext* context = getScriptExecutionContext();
1843 return V8Proxy::throwError(V8Proxy::ReferenceError, "${implClassName} constructor's associated context is not available", args.GetIsolate());
1847 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1848 push(@afterArgumentList, "ec");
1853 foreach my $parameter (@{$function->parameters}) {
1854 last if $index eq $paramIndex;
1855 if ($replacements{$parameter->name}) {
1856 push(@argumentList, $replacements{$parameter->name});
1858 push(@argumentList, $parameter->name);
1863 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
1864 push(@implContent, "\n");
1865 push(@implContent, " RefPtr<${implClassName}> impl = ${implClassName}::create(${argumentString});\n");
1866 push(@implContent, " v8::Handle<v8::Object> wrapper = args.Holder();\n");
1868 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1869 push(@implContent, " if (ec)\n");
1870 push(@implContent, " goto fail;\n");
1873 my $DOMObject = GetDomMapName($dataNode, $implClassName);
1874 push(@implContent, <<END);
1876 V8DOMWrapper::setDOMWrapper(wrapper, &info, impl.get());
1877 V8DOMWrapper::setJSWrapperFor${DOMObject}(impl.release(), v8::Persistent<v8::Object>::New(wrapper), args.GetIsolate());
1878 return args.Holder();
1881 if ($raisesExceptions) {
1882 push(@implContent, " fail:\n");
1883 push(@implContent, " return throwError(ec, args.GetIsolate());\n");
1886 push(@implContent, "}\n");
1887 push(@implContent, "\n");
1890 sub GenerateEventConstructorCallback
1892 my $dataNode = shift;
1893 my $implClassName = shift;
1895 AddToImplIncludes("Dictionary.h");
1896 AddToImplIncludes("V8BindingMacros.h");
1897 push(@implContent, <<END);
1898 v8::Handle<v8::Value> V8${implClassName}::constructorCallback(const v8::Arguments& args)
1900 INC_STATS("DOM.${implClassName}.Constructor");
1902 if (!args.IsConstructCall())
1903 return V8Proxy::throwTypeError("DOM object constructor cannot be called as a function.");
1905 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
1906 return args.Holder();
1908 if (args.Length() < 1)
1909 return V8Proxy::throwNotEnoughArgumentsError(args.GetIsolate());
1911 STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, type, args[0]);
1912 ${implClassName}Init eventInit;
1913 if (args.Length() >= 2) {
1914 EXCEPTION_BLOCK(Dictionary, options, args[1]);
1915 if (!fill${implClassName}Init(eventInit, options))
1916 return v8::Undefined();
1919 RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit);
1921 V8DOMWrapper::setDOMWrapper(args.Holder(), &info, event.get());
1922 V8DOMWrapper::setJSWrapperForDOMObject(event.release(), v8::Persistent<v8::Object>::New(args.Holder()), args.GetIsolate());
1923 return args.Holder();
1926 bool fill${implClassName}Init(${implClassName}Init& eventInit, const Dictionary& options)
1930 foreach my $interfaceBase (@{$dataNode->parents}) {
1931 push(@implContent, <<END);
1932 if (!fill${interfaceBase}Init(eventInit, options))
1938 for (my $index = 0; $index < @{$dataNode->attributes}; $index++) {
1939 my $attribute = @{$dataNode->attributes}[$index];
1940 if ($attribute->signature->extendedAttributes->{"InitializedByEventConstructor"}) {
1941 my $attributeName = $attribute->signature->name;
1942 push(@implContent, " options.get(\"$attributeName\", eventInit.$attributeName);\n");
1946 push(@implContent, <<END);
1953 sub GenerateNamedConstructorCallback
1955 my $function = shift;
1956 my $dataNode = shift;
1957 my $implClassName = shift;
1959 my $raisesExceptions = @{$function->raisesExceptions};
1960 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
1961 $raisesExceptions = 1;
1963 if (!$raisesExceptions) {
1964 foreach my $parameter (@{$function->parameters}) {
1965 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1966 $raisesExceptions = 1;
1971 my $maybeObserveFeature = GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"});
1973 my @beforeArgumentList;
1974 my @afterArgumentList;
1976 if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
1977 push(@implContent, <<END);
1978 WrapperTypeInfo V8${implClassName}Constructor::info = { V8${implClassName}Constructor::GetTemplate, V8${implClassName}::derefObject, V8${implClassName}::toActiveDOMObject, 0, 0, WrapperTypeObjectPrototype };
1982 push(@implContent, <<END);
1983 WrapperTypeInfo V8${implClassName}Constructor::info = { V8${implClassName}Constructor::GetTemplate, 0, 0, 0, 0, WrapperTypeObjectPrototype };
1988 push(@implContent, <<END);
1989 static v8::Handle<v8::Value> V8${implClassName}ConstructorCallback(const v8::Arguments& args)
1991 INC_STATS("DOM.${implClassName}.Constructor");
1992 ${maybeObserveFeature}
1993 if (!args.IsConstructCall())
1994 return V8Proxy::throwTypeError("DOM object constructor cannot be called as a function.");
1996 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
1997 return args.Holder();
1999 Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
2001 return V8Proxy::throwError(V8Proxy::ReferenceError, "${implClassName} constructor associated frame is unavailable", args.GetIsolate());
2003 Document* document = frame->document();
2005 // Make sure the document is added to the DOM Node map. Otherwise, the ${implClassName} instance
2006 // may end up being the only node in the map and get garbage-collected prematurely.
2007 toV8(document, args.GetIsolate());
2011 push(@implContent, GenerateArgumentsCountCheck($function, $dataNode));
2013 if ($raisesExceptions) {
2014 AddToImplIncludes("ExceptionCode.h");
2015 push(@implContent, "\n");
2016 push(@implContent, " ExceptionCode ec = 0;\n");
2019 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $implClassName);
2020 push(@implContent, $parameterCheckString);
2022 push(@beforeArgumentList, "document");
2024 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
2025 push(@afterArgumentList, "ec");
2030 foreach my $parameter (@{$function->parameters}) {
2031 last if $index eq $paramIndex;
2032 if ($replacements{$parameter->name}) {
2033 push(@argumentList, $replacements{$parameter->name});
2035 push(@argumentList, $parameter->name);
2040 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
2041 push(@implContent, "\n");
2042 push(@implContent, " RefPtr<${implClassName}> impl = ${implClassName}::createForJSConstructor(${argumentString});\n");
2043 push(@implContent, " v8::Handle<v8::Object> wrapper = args.Holder();\n");
2045 if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
2046 push(@implContent, " if (ec)\n");
2047 push(@implContent, " goto fail;\n");
2050 my $DOMObject = GetDomMapName($dataNode, $implClassName);
2051 push(@implContent, <<END);
2053 V8DOMWrapper::setDOMWrapper(wrapper, &V8${implClassName}Constructor::info, impl.get());
2054 V8DOMWrapper::setJSWrapperFor${DOMObject}(impl.release(), v8::Persistent<v8::Object>::New(wrapper), args.GetIsolate());
2055 return args.Holder();
2058 if ($raisesExceptions) {
2059 push(@implContent, " fail:\n");
2060 push(@implContent, " return throwError(ec, args.GetIsolate());\n");
2063 push(@implContent, "}\n");
2065 push(@implContent, <<END);
2067 v8::Persistent<v8::FunctionTemplate> V8${implClassName}Constructor::GetTemplate()
2069 static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
2070 if (!cachedTemplate.IsEmpty())
2071 return cachedTemplate;
2073 v8::HandleScope scope;
2074 v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8${implClassName}ConstructorCallback);
2076 v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
2077 instance->SetInternalFieldCount(V8${implClassName}::internalFieldCount);
2078 result->SetClassName(v8::String::New("${implClassName}"));
2079 result->Inherit(V8${implClassName}::GetTemplate());
2081 cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result);
2082 return cachedTemplate;
2088 sub GenerateBatchedAttributeData
2090 my $dataNode = shift;
2091 my $interfaceName = $dataNode->name;
2092 my $attributes = shift;
2094 foreach my $attribute (@$attributes) {
2095 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
2096 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2097 GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
2098 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2102 sub GenerateSingleBatchedAttribute
2104 my $interfaceName = shift;
2105 my $attribute = shift;
2106 my $delimiter = shift;
2108 my $attrName = $attribute->signature->name;
2109 my $attrExt = $attribute->signature->extendedAttributes;
2111 my $accessControl = "v8::DEFAULT";
2112 if ($attrExt->{"DoNotCheckSecurityOnGetter"}) {
2113 $accessControl = "v8::ALL_CAN_READ";
2114 } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) {
2115 $accessControl = "v8::ALL_CAN_WRITE";
2116 } elsif ($attrExt->{"DoNotCheckSecurity"}) {
2117 $accessControl = "v8::ALL_CAN_READ";
2118 if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) {
2119 $accessControl .= " | v8::ALL_CAN_WRITE";
2122 if ($attrExt->{"V8Unforgeable"}) {
2123 $accessControl .= " | v8::PROHIBITS_OVERWRITING";
2125 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
2127 my $customAccessor =
2128 $attrExt->{"Custom"} ||
2129 $attrExt->{"CustomSetter"} ||
2130 $attrExt->{"CustomGetter"} ||
2131 $attrExt->{"V8Custom"} ||
2132 $attrExt->{"V8CustomSetter"} ||
2133 $attrExt->{"V8CustomGetter"} ||
2135 if ($customAccessor eq "VALUE_IS_MISSING") {
2136 # use the naming convension, interface + (capitalize) attr name
2137 $customAccessor = $interfaceName . "::" . $attrName;
2142 my $propAttr = "v8::None";
2143 my $hasCustomSetter = 0;
2146 if ($attrExt->{"NotEnumerable"}) {
2147 $propAttr .= " | v8::DontEnum";
2149 if ($attrExt->{"V8Unforgeable"}) {
2150 $propAttr .= " | v8::DontDelete";
2153 my $on_proto = "0 /* on instance */";
2154 my $data = "0 /* no data */";
2157 if ($attribute->signature->type =~ /Constructor$/) {
2158 my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
2159 $constructorType =~ s/Constructor$//;
2160 # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
2161 # We do not generate the header file for NamedConstructor of class XXXX,
2162 # since we generate the NamedConstructor declaration into the header file of class XXXX.
2163 if ($constructorType !~ /Constructor$/ || $attribute->signature->extendedAttributes->{"V8CustomConstructor"} || $attribute->signature->extendedAttributes->{"CustomConstructor"}) {
2164 AddToImplIncludes("V8${constructorType}.h", $attribute->signature->extendedAttributes->{"Conditional"});
2166 if ($customAccessor) {
2167 $getter = "V8${customAccessor}AccessorGetter";
2169 $data = "&V8${constructorType}::info";
2170 $getter = "${interfaceName}V8Internal::${interfaceName}ConstructorGetter";
2172 $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter";
2174 # Default Getter and Setter
2175 $getter = "${interfaceName}V8Internal::${attrName}AttrGetter";
2176 $setter = "${interfaceName}V8Internal::${attrName}AttrSetter";
2178 if ($attrExt->{"Replaceable"}) {
2179 $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter";
2183 if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2184 $hasCustomSetter = 1;
2185 $setter = "V8${customAccessor}AccessorSetter";
2189 if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
2190 $getter = "V8${customAccessor}AccessorGetter";
2194 # Read only attributes
2195 if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) {
2199 # An accessor can be installed on the proto
2200 if ($attrExt->{"V8OnProto"}) {
2201 $on_proto = "1 /* on proto */";
2204 my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
2205 "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2207 push(@implContent, $indent . " \/\/ $commentInfo\n");
2208 push(@implContent, $indent . " {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
2211 sub IsStandardFunction
2213 my $dataNode = shift;
2214 my $function = shift;
2216 my $interfaceName = $dataNode->name;
2217 my $attrExt = $function->signature->extendedAttributes;
2218 return 0 if $attrExt->{"V8Unforgeable"};
2219 return 0 if $function->isStatic;
2220 return 0 if $attrExt->{"V8EnabledAtRuntime"};
2221 return 0 if $attrExt->{"V8EnabledPerContext"};
2222 return 0 if RequiresCustomSignature($function);
2223 return 0 if $attrExt->{"V8DoNotCheckSignature"};
2224 return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($dataNode->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow"));
2225 return 0 if $attrExt->{"NotEnumerable"};
2226 return 0 if $attrExt->{"V8ReadOnly"};
2230 sub GenerateNonStandardFunction
2232 my $dataNode = shift;
2233 my $function = shift;
2235 my $interfaceName = $dataNode->name;
2236 my $attrExt = $function->signature->extendedAttributes;
2237 my $name = $function->signature->name;
2239 my $property_attributes = "v8::DontDelete";
2240 if ($attrExt->{"NotEnumerable"}) {
2241 $property_attributes .= " | v8::DontEnum";
2243 if ($attrExt->{"V8ReadOnly"}) {
2244 $property_attributes .= " | v8::ReadOnly";
2247 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2249 my $template = "proto";
2250 if ($attrExt->{"V8Unforgeable"}) {
2251 $template = "instance";
2253 if ($function->isStatic) {
2257 my $conditional = "";
2258 if ($attrExt->{"V8EnabledAtRuntime"}) {
2259 # Only call Set()/SetAccessor() if this method should be enabled
2260 my $enable_function = GetRuntimeEnableFunctionName($function->signature);
2261 $conditional = "if (${enable_function}())\n ";
2263 if ($attrExt->{"V8EnabledPerContext"}) {
2264 # Only call Set()/SetAccessor() if this method should be enabled
2265 my $enable_function = GetContextEnableFunction($function->signature);
2266 $conditional = "if (${enable_function}(impl->document()))\n ";
2269 if ($attrExt->{"DoNotCheckSecurity"} &&
2270 ($dataNode->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow")) {
2271 # Mark the accessor as ReadOnly and set it on the proto object so
2272 # it can be shadowed. This is really a hack to make it work.
2273 # There are several sceneria to call into the accessor:
2274 # 1) from the same domain: "window.open":
2275 # the accessor finds the DOM wrapper in the proto chain;
2276 # 2) from the same domain: "window.__proto__.open":
2277 # the accessor will NOT find a DOM wrapper in the prototype chain
2278 # 3) from another domain: "window.open":
2279 # the access find the DOM wrapper in the prototype chain
2280 # "window.__proto__.open" from another domain will fail when
2281 # accessing '__proto__'
2283 # The solution is very hacky and fragile, it really needs to be replaced
2284 # by a better solution.
2285 $property_attributes .= " | v8::ReadOnly";
2286 push(@implContent, <<END);
2289 ${conditional}$template->SetAccessor(v8::String::New("$name"), ${interfaceName}V8Internal::${name}AttrGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
2294 my $signature = "defaultSignature";
2295 if ($attrExt->{"V8DoNotCheckSignature"} || $function->isStatic) {
2296 $signature = "v8::Local<v8::Signature>()";
2299 if (RequiresCustomSignature($function)) {
2300 $signature = "${name}Signature";
2301 push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function));
2304 # Normal function call is a template
2305 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2307 if ($property_attributes eq "v8::DontDelete") {
2308 $property_attributes = "";
2310 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2313 if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2314 die "This shouldn't happen: Intraface '$interfaceName' $commentInfo\n";
2317 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2318 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2320 push(@implContent, " ${conditional}$template->Set(v8::String::New(\"$name\"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes);\n");
2322 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2325 sub GenerateImplementationIndexer
2327 my $dataNode = shift;
2328 my $indexer = shift;
2329 my $interfaceName = $dataNode->name;
2331 # FIXME: Figure out what NumericIndexedGetter is really supposed to do. Right now, it's only set on WebGL-related files.
2332 my $hasCustomSetter = $dataNode->extendedAttributes->{"CustomIndexedSetter"} && !$dataNode->extendedAttributes->{"NumericIndexedGetter"};
2333 my $hasGetter = $dataNode->extendedAttributes->{"IndexedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
2335 # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
2336 # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
2337 # simplistic, mirrored indexer handling in addition to named property handling.
2338 my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
2339 if ($isSpecialCase) {
2341 if ($dataNode->extendedAttributes->{"CustomNamedSetter"}) {
2342 $hasCustomSetter = 1;
2346 my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode);
2348 # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
2349 if ($interfaceName eq "HTMLOptionsCollection") {
2358 AddToImplIncludes("V8Collection.h");
2361 $indexer = $codeGenerator->FindSuperMethod($dataNode, "item");
2364 my $indexerType = $indexer ? $indexer->type : 0;
2366 # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
2367 if ($interfaceName eq "WebKitCSSKeyframesRule") {
2368 $indexerType = "WebKitCSSKeyframeRule";
2371 if ($indexerType && !$hasCustomSetter) {
2372 if ($indexerType eq "DOMString") {
2373 my $conversion = $indexer->extendedAttributes->{"TreatReturnedNullStringAs"};
2374 if ($conversion && $conversion eq "Null") {
2375 push(@implContent, <<END);
2376 setCollectionStringOrUndefinedIndexedGetter<${interfaceName}>(desc);
2379 push(@implContent, <<END);
2380 setCollectionStringIndexedGetter<${interfaceName}>(desc);
2384 push(@implContent, <<END);
2385 setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
2387 # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
2388 AddToImplIncludes("V8${indexerType}.h");
2394 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
2395 my $setOn = "Instance";
2397 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2398 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2399 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2401 if ($interfaceName eq "DOMWindow") {
2402 $setOn = "Prototype";
2406 push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter");
2407 push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0");
2408 push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
2409 push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0");
2410 push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
2411 push(@implContent, ");\n");
2414 sub GenerateImplementationNamedPropertyGetter
2416 my $dataNode = shift;
2417 my $namedPropertyGetter = shift;
2418 my $interfaceName = $dataNode->name;
2419 my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"CustomNamedGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
2421 # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit
2422 # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection).
2423 if ($interfaceName eq "HTMLOptionsCollection") {
2424 $interfaceName = "HTMLCollection";
2425 $hasCustomNamedGetter = 1;
2428 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
2429 $hasCustomNamedGetter = 1;
2432 if ($interfaceName eq "HTMLDocument") {
2433 $hasCustomNamedGetter = 0;
2436 my $hasGetter = $dataNode->extendedAttributes->{"NamedGetter"} || $hasCustomNamedGetter;
2441 if (!$namedPropertyGetter) {
2442 $namedPropertyGetter = $codeGenerator->FindSuperMethod($dataNode, "namedItem");
2445 if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomNamedGetter) {
2446 AddToImplIncludes("V8Collection.h");
2447 my $type = $namedPropertyGetter->type;
2448 push(@implContent, <<END);
2449 setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
2454 my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"CustomNamedSetter"};
2455 my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"};
2456 my $hasEnumerator = $dataNode->extendedAttributes->{"CustomEnumerateProperty"};
2457 my $setOn = "Instance";
2459 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2460 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2461 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2463 if ($interfaceName eq "DOMWindow") {
2464 $setOn = "Prototype";
2469 push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, ");
2470 push(@implContent, $hasCustomNamedSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, ");
2471 # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
2472 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyQuery, " : "0, ");
2473 push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, ");
2474 push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0");
2475 push(@implContent, ");\n");
2478 sub GenerateImplementationCustomCall
2480 my $dataNode = shift;
2481 my $interfaceName = $dataNode->name;
2482 my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"};
2484 if ($hasCustomCall) {
2485 push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
2489 sub GenerateImplementationMasqueradesAsUndefined
2491 my $dataNode = shift;
2492 if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"})
2494 push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n");
2498 sub IsTypedArrayType
2501 return 1 if (($type eq "ArrayBuffer") or ($type eq "ArrayBufferView"));
2502 return 1 if (($type eq "Uint8Array") or ($type eq "Uint8ClampedArray") or ($type eq "Uint16Array") or ($type eq "Uint32Array"));
2503 return 1 if (($type eq "Int8Array") or ($type eq "Int16Array") or ($type eq "Int32Array"));
2504 return 1 if (($type eq "Float32Array") or ($type eq "Float64Array"));
2509 sub GenerateImplementation
2512 my $dataNode = shift;
2513 my $interfaceName = $dataNode->name;
2514 my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($dataNode);
2515 my $className = "V8$interfaceName";
2516 my $implClassName = $interfaceName;
2518 # - Add default header template
2519 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
2521 AddToImplIncludes("RuntimeEnabledFeatures.h");
2522 AddToImplIncludes("ContextFeatures.h");
2523 AddToImplIncludes("V8Proxy.h");
2524 AddToImplIncludes("V8Binding.h");
2525 AddToImplIncludes("V8BindingState.h");
2526 AddToImplIncludes("V8DOMWrapper.h");
2527 AddToImplIncludes("V8IsolatedContext.h");
2529 AddIncludesForType($interfaceName);
2531 my $toActive = $dataNode->extendedAttributes->{"ActiveDOMObject"} ? "${className}::toActiveDOMObject" : "0";
2532 my $domVisitor = NeedsToVisitDOMWrapper($dataNode) ? "${className}::visitDOMWrapper" : "0";
2534 # Find the super descriptor.
2535 my $parentClass = "";
2536 my $parentClassTemplate = "";
2537 foreach (@{$dataNode->parents}) {
2538 my $parent = $codeGenerator->StripModule($_);
2539 if ($parent eq "EventTarget") {
2542 AddToImplIncludes("V8${parent}.h");
2543 $parentClass = "V8" . $parent;
2544 $parentClassTemplate = $parentClass . "::GetTemplate()";
2547 push(@implContentDecls, "namespace WebCore {\n\n");
2548 my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
2550 my $WrapperTypePrototype = $dataNode->isException ? "WrapperTypeErrorPrototype" : "WrapperTypeObjectPrototype";
2552 push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, $toActive, $domVisitor, $parentClassInfo, $WrapperTypePrototype };\n\n");
2553 push(@implContentDecls, "namespace ${interfaceName}V8Internal {\n\n");
2555 push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
2557 my $hasConstructors = 0;
2558 my $hasReplaceable = 0;
2560 # Generate property accessors for attributes.
2561 for (my $index = 0; $index < @{$dataNode->attributes}; $index++) {
2562 my $attribute = @{$dataNode->attributes}[$index];
2563 my $attrType = $attribute->signature->type;
2565 # Generate special code for the constructor attributes.
2566 if ($attrType =~ /Constructor$/) {
2567 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2568 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2569 $hasConstructors = 1;
2574 if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
2575 $attribute->signature->extendedAttributes->{"V8OnProto"} = 1;
2578 if ($attrType eq "SerializedScriptValue") {
2579 AddToImplIncludes("SerializedScriptValue.h");
2582 # Do not generate accessor if this is a custom attribute. The
2583 # call will be forwarded to a hand-written accessor
2585 if ($attribute->signature->extendedAttributes->{"Custom"} ||
2586 $attribute->signature->extendedAttributes->{"V8Custom"}) {
2590 # Generate the accessor.
2591 if (!($attribute->signature->extendedAttributes->{"CustomGetter"} ||
2592 $attribute->signature->extendedAttributes->{"V8CustomGetter"})) {
2593 GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName);
2596 if ($attribute->signature->extendedAttributes->{"Replaceable"}) {
2597 $hasReplaceable = 1;
2598 } elsif (!$attribute->signature->extendedAttributes->{"CustomSetter"} &&
2599 !$attribute->signature->extendedAttributes->{"V8CustomSetter"} &&
2600 $attribute->type !~ /^readonly/ &&
2601 !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) {
2602 GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName);
2606 if ($hasConstructors) {
2607 GenerateConstructorGetter($dataNode, $implClassName);
2610 if ($hasConstructors || $hasReplaceable) {
2611 GenerateReplaceableAttrSetter($dataNode, $implClassName);
2614 if (NeedsToVisitDOMWrapper($dataNode)) {
2615 GenerateVisitDOMWrapper($dataNode, $implClassName);
2619 my $namedPropertyGetter;
2620 my @enabledPerContextFunctions;
2621 my @normalFunctions;
2622 # Generate methods for functions.
2623 foreach my $function (@{$dataNode->functions}) {
2624 my $isCustom = $function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"};
2626 GenerateFunctionCallback($function, $dataNode, $implClassName);
2627 if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) {
2628 GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName);
2632 if ($function->signature->name eq "item") {
2633 $indexer = $function->signature;
2636 if ($function->signature->name eq "namedItem") {
2637 $namedPropertyGetter = $function->signature;
2640 # If the function does not need domain security check, we need to
2641 # generate an access getter that returns different function objects
2642 # for different calling context.
2643 if (($dataNode->extendedAttributes->{"CheckSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2644 if (!$isCustom || $function->{overloadIndex} == 1) {
2645 GenerateDomainSafeFunctionGetter($function, $implClassName);
2649 # Separate out functions that are enabled per context so we can process them specially.
2650 if ($function->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2651 push(@enabledPerContextFunctions, $function);
2653 push(@normalFunctions, $function);
2658 my $attributes = $dataNode->attributes;
2660 # For the DOMWindow interface we partition the attributes into the
2661 # ones that disallows shadowing and the rest.
2662 my @disallowsShadowing;
2663 # Also separate out attributes that are enabled at runtime so we can process them specially.
2664 my @enabledAtRuntimeAttributes;
2665 my @enabledPerContextAttributes;
2666 my @normalAttributes;
2667 foreach my $attribute (@$attributes) {
2669 if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8Unforgeable"}) {
2670 push(@disallowsShadowing, $attribute);
2671 } elsif ($attribute->signature->extendedAttributes->{"V8EnabledAtRuntime"}) {
2672 push(@enabledAtRuntimeAttributes, $attribute);
2673 } elsif ($attribute->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2674 push(@enabledPerContextAttributes, $attribute);
2676 push(@normalAttributes, $attribute);
2679 $attributes = \@normalAttributes;
2680 # Put the attributes that disallow shadowing on the shadow object.
2681 if (@disallowsShadowing) {
2682 push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n");
2683 GenerateBatchedAttributeData($dataNode, \@disallowsShadowing);
2684 push(@implContent, "};\n\n");
2687 my $has_attributes = 0;
2689 $has_attributes = 1;
2690 push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n");
2691 GenerateBatchedAttributeData($dataNode, $attributes);
2692 push(@implContent, "};\n\n");
2695 # Setup table of standard callback functions
2696 my $num_callbacks = 0;
2697 my $has_callbacks = 0;
2698 foreach my $function (@normalFunctions) {
2699 # Only one table entry is needed for overloaded methods:
2700 next if $function->{overloadIndex} > 1;
2701 # Don't put any nonstandard functions into this table:
2702 next if !IsStandardFunction($dataNode, $function);
2703 if (!$has_callbacks) {
2705 push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n");
2707 my $name = $function->signature->name;
2708 my $callback = GetFunctionTemplateCallbackName($function, $interfaceName);
2709 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2710 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2711 push(@implContent, <<END);
2712 {"$name", $callback},
2714 push(@implContent, "#endif\n") if $conditionalString;
2717 push(@implContent, "};\n\n") if $has_callbacks;
2720 my $has_constants = 0;
2721 my @constantsEnabledAtRuntime;
2722 if (@{$dataNode->constants}) {
2724 push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n");
2726 foreach my $constant (@{$dataNode->constants}) {
2727 my $name = $constant->name;
2728 my $value = $constant->value;
2729 my $attrExt = $constant->extendedAttributes;
2730 my $conditional = $attrExt->{"Conditional"};
2731 my $implementedBy = $attrExt->{"ImplementedBy"};
2732 if ($implementedBy) {
2733 AddToImplIncludes("${implementedBy}.h");
2735 if ($attrExt->{"V8EnabledAtRuntime"}) {
2736 push(@constantsEnabledAtRuntime, $constant);
2738 # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
2739 # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we
2740 # handled this here, and converted it to a -1 constant in the c++ output.
2742 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2743 push(@implContent, "#if ${conditionalString}\n");
2745 push(@implContent, <<END);
2746 {"${name}", static_cast<signed int>($value)},
2748 push(@implContent, "#endif\n") if $conditional;
2751 if ($has_constants) {
2752 push(@implContent, "};\n\n");
2753 push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode));
2756 push(@implContentDecls, "} // namespace ${interfaceName}V8Internal\n\n");
2758 if ($dataNode->extendedAttributes->{"NamedConstructor"} && !($dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
2759 GenerateNamedConstructorCallback($dataNode->constructor, $dataNode, $interfaceName);
2760 } elsif ($dataNode->extendedAttributes->{"Constructor"} && !($dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
2761 GenerateConstructorCallback($dataNode->constructor, $dataNode, $interfaceName);
2762 } elsif (IsConstructorTemplate($dataNode, "Event")) {
2763 GenerateEventConstructorCallback($dataNode, $interfaceName);
2766 my $access_check = "";
2767 if ($dataNode->extendedAttributes->{"CheckSecurity"} && !($interfaceName eq "DOMWindow")) {
2768 $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));";
2771 # For the DOMWindow interface, generate the shadow object template
2772 # configuration method.
2773 if ($implClassName eq "DOMWindow") {
2774 push(@implContent, <<END);
2775 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ)
2777 batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs));
2779 // Install a security handler with V8.
2780 templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info));
2781 templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2787 if (!$parentClassTemplate) {
2788 $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
2791 # Generate the template configuration method
2792 push(@implContent, <<END);
2793 static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc)
2795 desc->ReadOnlyPrototype();
2797 v8::Local<v8::Signature> defaultSignature;
2799 if ($dataNode->extendedAttributes->{"V8EnabledAtRuntime"}) {
2800 my $enable_function = GetRuntimeEnableFunctionName($dataNode);
2801 push(@implContent, <<END);
2802 if (!${enable_function}())
2803 defaultSignature = configureTemplate(desc, \"\", $parentClassTemplate, V8${interfaceName}::internalFieldCount, 0, 0, 0, 0);
2807 push(@implContent, <<END);
2808 defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount,
2810 # Set up our attributes if we have them
2811 if ($has_attributes) {
2812 push(@implContent, <<END);
2813 ${interfaceName}Attrs, WTF_ARRAY_LENGTH(${interfaceName}Attrs),
2816 push(@implContent, <<END);
2821 if ($has_callbacks) {
2822 push(@implContent, <<END);
2823 ${interfaceName}Callbacks, WTF_ARRAY_LENGTH(${interfaceName}Callbacks));
2826 push(@implContent, <<END);
2831 AddToImplIncludes("wtf/UnusedParam.h");
2832 push(@implContent, <<END);
2833 UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
2836 if (IsConstructable($dataNode)) {
2837 push(@implContent, <<END);
2838 desc->SetCallHandler(V8${interfaceName}::constructorCallback);
2842 if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has_constants) {
2843 push(@implContent, <<END);
2844 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
2845 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
2846 UNUSED_PARAM(instance); // In some cases, it will not be used.
2847 UNUSED_PARAM(proto); // In some cases, it will not be used.
2851 push(@implContent, " $access_check\n");
2853 # Setup the enable-at-runtime attrs if we have them
2854 foreach my $runtime_attr (@enabledAtRuntimeAttributes) {
2855 my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
2856 my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_attr->signature);
2857 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2858 push(@implContent, " if (${enable_function}()) {\n");
2859 push(@implContent, " static const BatchedAttribute attrData =\\\n");
2860 GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " ");
2861 push(@implContent, <<END);
2862 configureAttribute(instance, proto, attrData);
2865 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2868 # Setup the enable-at-runtime constants if we have them
2869 foreach my $runtime_const (@constantsEnabledAtRuntime) {
2870 my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
2871 my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_const);
2872 my $name = $runtime_const->name;
2873 my $value = $runtime_const->value;
2874 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2875 push(@implContent, " if (${enable_function}()) {\n");
2876 push(@implContent, <<END);
2877 static const BatchedConstant constData = {"${name}", static_cast<signed int>(${value})};
2878 batchConfigureConstants(desc, proto, &constData, 1);
2880 push(@implContent, " }\n");
2881 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
2884 GenerateImplementationIndexer($dataNode, $indexer);
2885 GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter);
2886 GenerateImplementationCustomCall($dataNode);
2887 GenerateImplementationMasqueradesAsUndefined($dataNode);
2889 # Define our functions with Set() or SetAccessor()
2890 my $total_functions = 0;
2891 foreach my $function (@normalFunctions) {
2892 # Only one accessor is needed for overloaded methods:
2893 next if $function->{overloadIndex} > 1;
2896 next if IsStandardFunction($dataNode, $function);
2897 GenerateNonStandardFunction($dataNode, $function);
2901 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
2903 if ($has_constants) {
2904 push(@implContent, <<END);
2905 batchConfigureConstants(desc, proto, ${interfaceName}Consts, WTF_ARRAY_LENGTH(${interfaceName}Consts));
2910 if ($interfaceName eq "DOMWindow") {
2911 push(@implContent, <<END);
2913 proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2914 desc->SetHiddenPrototype(true);
2915 instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2916 // Set access check callbacks, but turned off initially.
2917 // When a context is detached from a frame, turn on the access check.
2918 // Turning on checks also invalidates inline caches of the object.
2919 instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false);
2922 if ($interfaceName eq "HTMLDocument") {
2923 push(@implContent, <<END);
2924 desc->SetHiddenPrototype(true);
2927 if ($interfaceName eq "Location") {
2928 push(@implContent, <<END);
2930 // For security reasons, these functions are on the instance instead
2931 // of on the prototype object to ensure that they cannot be overwritten.
2932 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));
2933 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));
2934 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));
2938 my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
2939 push(@implContent, <<END);
2941 // Custom toString template
2942 desc->Set(getToStringName(), getToStringTemplate());
2946 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate()
2948 V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
2949 V8BindingPerIsolateData::TemplateMap::iterator result = data->rawTemplateMap().find(&info);
2950 if (result != data->rawTemplateMap().end())
2951 return result->second;
2953 v8::HandleScope handleScope;
2954 v8::Persistent<v8::FunctionTemplate> templ = createRawTemplate();
2955 data->rawTemplateMap().add(&info, templ);
2959 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()
2961 V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
2962 V8BindingPerIsolateData::TemplateMap::iterator result = data->templateMap().find(&info);
2963 if (result != data->templateMap().end())
2964 return result->second;
2966 v8::HandleScope handleScope;
2967 v8::Persistent<v8::FunctionTemplate> templ =
2968 Configure${className}Template(GetRawTemplate());
2969 data->templateMap().add(&info, templ);
2973 bool ${className}::HasInstance(v8::Handle<v8::Value> value)
2975 return GetRawTemplate()->HasInstance(value);
2980 if (@enabledPerContextAttributes or @enabledPerContextFunctions) {
2981 push(@implContent, <<END);
2982 void ${className}::installPerContextProperties(v8::Handle<v8::Object> instance, ${implClassName}* impl)
2984 v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetPrototype());
2985 // When building QtWebkit with V8 this variable is unused when none of the features are enabled.
2986 UNUSED_PARAM(proto);
2989 if (@enabledPerContextAttributes) {
2990 # Setup the enable-by-settings attrs if we have them
2991 foreach my $runtimeAttr (@enabledPerContextAttributes) {
2992 my $enableFunction = GetContextEnableFunction($runtimeAttr->signature);
2993 my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeAttr->signature);
2994 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
2995 push(@implContent, " if (${enableFunction}(impl->document())) {\n");
2996 push(@implContent, " static const BatchedAttribute attrData =\\\n");
2997 GenerateSingleBatchedAttribute($interfaceName, $runtimeAttr, ";", " ");
2998 push(@implContent, <<END);
2999 configureAttribute(instance, proto, attrData);
3001 push(@implContent, " }\n");
3002 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3006 # Setup the enable-by-settings functions if we have them
3007 if (@enabledPerContextFunctions) {
3008 push(@implContent, <<END);
3009 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate());
3010 UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
3013 foreach my $runtimeFunc (@enabledPerContextFunctions) {
3014 my $enableFunction = GetContextEnableFunction($runtimeFunc->signature);
3015 my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeFunc->signature);
3016 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3017 push(@implContent, " if (${enableFunction}(impl->document())) {\n");
3018 my $name = $runtimeFunc->signature->name;
3019 my $callback = GetFunctionTemplateCallbackName($runtimeFunc, $interfaceName);
3020 push(@implContent, <<END);
3021 proto->Set(v8::String::New("${name}"), v8::FunctionTemplate::New(${callback}, v8::Handle<v8::Value>(), defaultSignature)->GetFunction());
3023 push(@implContent, " }\n");
3024 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3028 push(@implContent, <<END);
3033 if ($dataNode->extendedAttributes->{"ActiveDOMObject"}) {
3034 # MessagePort is handled like an active dom object even though it doesn't inherit
3035 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
3036 my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
3037 push(@implContent, <<END);
3038 ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object)
3040 return ${returnValue};
3045 if ($implClassName eq "DOMWindow") {
3046 push(@implContent, <<END);
3047 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate()
3049 static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
3050 if (V8DOMWindowShadowObjectCache.IsEmpty()) {
3051 V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
3052 ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache);
3054 return V8DOMWindowShadowObjectCache;
3059 GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType);
3061 push(@implContent, <<END);
3063 void ${className}::derefObject(void* object)
3065 static_cast<${nativeType}*>(object)->deref();
3068 } // namespace WebCore
3071 my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3072 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3074 # We've already added the header for this file in implFixedHeader, so remove
3075 # it from implIncludes to ensure we don't #include it twice.
3076 delete $implIncludes{"${className}.h"};
3079 sub GenerateHeaderContentHeader
3081 my $dataNode = shift;
3082 my $className = "V8" . $dataNode->name;
3083 my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3085 my @headerContentHeader = split("\r", $headerTemplate);
3087 push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
3088 push(@headerContentHeader, "\n#ifndef ${className}" . "_h");
3089 push(@headerContentHeader, "\n#define ${className}" . "_h\n\n");
3090 return @headerContentHeader;
3093 sub GenerateImplementationContentHeader
3095 my $dataNode = shift;
3096 my $className = "V8" . $dataNode->name;
3097 my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3099 my @implContentHeader = split("\r", $headerTemplate);
3101 push(@implContentHeader, "\n#include \"config.h\"\n");
3102 push(@implContentHeader, "#include \"${className}.h\"\n\n");
3103 push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
3104 return @implContentHeader;
3107 sub GenerateCallbackHeader
3110 my $dataNode = shift;
3112 my $interfaceName = $dataNode->name;
3113 my $className = "V8$interfaceName";
3116 # - Add default header template
3117 push(@headerContent, GenerateHeaderContentHeader($dataNode));
3119 my @unsortedIncludes = ();
3120 push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\"");
3121 push(@unsortedIncludes, "#include \"$interfaceName.h\"");
3122 push(@unsortedIncludes, "#include \"WorldContextHandle.h\"");
3123 push(@unsortedIncludes, "#include <v8.h>");
3124 push(@unsortedIncludes, "#include <wtf/Forward.h>");
3125 push(@headerContent, join("\n", sort @unsortedIncludes));
3127 push(@headerContent, "\n\nnamespace WebCore {\n\n");
3128 push(@headerContent, "class ScriptExecutionContext;\n\n");
3129 push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n");
3131 push(@headerContent, <<END);
3133 static PassRefPtr<${className}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
3135 ASSERT(value->IsObject());
3137 return adoptRef(new ${className}(value->ToObject(), context));
3140 virtual ~${className}();
3145 my $numFunctions = @{$dataNode->functions};
3146 if ($numFunctions > 0) {
3147 push(@headerContent, " // Functions\n");
3148 foreach my $function (@{$dataNode->functions}) {
3149 my @params = @{$function->parameters};
3150 if (!$function->signature->extendedAttributes->{"Custom"} &&
3151 !(GetNativeType($function->signature->type) eq "bool")) {
3152 push(@headerContent, " COMPILE_ASSERT(false)");
3155 push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
3158 foreach my $param (@params) {
3159 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
3161 push(@headerContent, join(", ", @args));
3162 push(@headerContent, ");\n");
3166 push(@headerContent, <<END);
3169 ${className}(v8::Local<v8::Object>, ScriptExecutionContext*);
3171 v8::Persistent<v8::Object> m_callback;
3172 WorldContextHandle m_worldContext;
3177 push(@headerContent, "}\n\n");
3178 push(@headerContent, "#endif // $className" . "_h\n\n");
3180 my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3181 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
3184 sub GenerateCallbackImplementation
3187 my $dataNode = shift;
3188 my $interfaceName = $dataNode->name;
3189 my $className = "V8$interfaceName";
3191 # - Add default header template
3192 push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
3194 AddToImplIncludes("ScriptExecutionContext.h");
3195 AddToImplIncludes("V8Binding.h");
3196 AddToImplIncludes("V8CustomVoidCallback.h");
3197 AddToImplIncludes("V8Proxy.h");
3199 push(@implContent, "#include <wtf/Assertions.h>\n\n");
3200 push(@implContent, "namespace WebCore {\n\n");
3201 push(@implContent, <<END);
3202 ${className}::${className}(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
3203 : ActiveDOMCallback(context)
3204 , m_callback(v8::Persistent<v8::Object>::New(callback))
3205 , m_worldContext(UseCurrentWorld)
3209 ${className}::~${className}()
3211 m_callback.Dispose();
3217 my $numFunctions = @{$dataNode->functions};
3218 if ($numFunctions > 0) {
3219 push(@implContent, "// Functions\n");
3220 foreach my $function (@{$dataNode->functions}) {
3221 my @params = @{$function->parameters};
3222 if ($function->signature->extendedAttributes->{"Custom"} ||
3223 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
3227 AddIncludesForType($function->signature->type);
3228 push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(");
3232 my $thisType = $function->signature->extendedAttributes->{"PassThisToCallback"};
3233 foreach my $param (@params) {
3234 my $paramName = $param->name;
3235 AddIncludesForType($param->type);
3236 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $paramName);
3237 if ($thisType and $thisType eq $param->type) {
3238 push(@argsCheck, <<END);
3239 ASSERT(${paramName});
3244 push(@implContent, join(", ", @args));
3246 push(@implContent, ")\n");
3247 push(@implContent, "{\n");
3248 push(@implContent, @argsCheck) if @argsCheck;
3249 push(@implContent, " if (!canInvokeCallback())\n");
3250 push(@implContent, " return true;\n\n");
3251 push(@implContent, " v8::HandleScope handleScope;\n\n");
3252 push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n");
3253 push(@implContent, " if (v8Context.IsEmpty())\n");
3254 push(@implContent, " return true;\n\n");
3255 push(@implContent, " v8::Context::Scope scope(v8Context);\n\n");
3258 foreach my $param (@params) {
3259 my $paramName = $param->name;
3260 push(@implContent, " v8::Handle<v8::Value> ${paramName}Handle = " . NativeToJSValue($param, $paramName) . ";\n");
3261 push(@implContent, " if (${paramName}Handle.IsEmpty()) {\n");
3262 push(@implContent, " if (!isScriptControllerTerminating())\n");
3263 push(@implContent, " CRASH();\n");
3264 push(@implContent, " return true;\n");
3265 push(@implContent, " }\n");
3266 push(@args, " ${paramName}Handle");
3269 if (scalar(@args) > 0) {
3270 push(@implContent, "\n v8::Handle<v8::Value> argv[] = {\n");
3271 push(@implContent, join(",\n", @args));
3272 push(@implContent, "\n };\n\n");
3274 push(@implContent, "\n v8::Handle<v8::Value> *argv = 0;\n\n");
3276 push(@implContent, " bool callbackReturnValue = false;\n");
3278 foreach my $param (@params) {
3279 next if $param->type ne $thisType;
3280 my $paramName = $param->name;
3281 push(@implContent, " return !invokeCallback(m_callback, v8::Handle<v8::Object>::Cast(${paramName}Handle), " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
3285 push(@implContent, " return !invokeCallback(m_callback, " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
3287 push(@implContent, "}\n");
3291 push(@implContent, "\n} // namespace WebCore\n\n");
3293 my $conditionalString = $codeGenerator->GenerateConditionalString($dataNode);
3294 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3297 sub GenerateToV8Converters
3299 my $dataNode = shift;
3300 my $interfaceName = shift;
3301 my $className = shift;
3302 my $nativeType = shift;
3304 my $domMapName = GetDomMapName($dataNode, $interfaceName);
3305 my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
3306 my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
3307 my $wrapSlowArgumentType = GetPassRefPtrType($nativeType);
3309 push(@implContent, <<END);
3311 v8::Handle<v8::Object> ${className}::wrapSlow(${wrapSlowArgumentType} impl, v8::Isolate* isolate)
3313 v8::Handle<v8::Object> wrapper;
3317 if (IsNodeSubType($dataNode)) {
3318 $proxyInit = "V8Proxy::retrieve(impl->document()->frame())";
3319 # DocumentType nodes are the only nodes that may have a NULL document.
3320 if ($interfaceName eq "DocumentType") {
3321 $proxyInit = "impl->document() ? $proxyInit : 0";
3326 push(@implContent, <<END);
3327 V8Proxy* proxy = $proxyInit;
3330 if (IsSubType($dataNode, "Document")) {
3331 push(@implContent, <<END);
3332 if (proxy && proxy->windowShell()->context().IsEmpty() && proxy->windowShell()->initContextIfNeeded()) {
3333 // initContextIfNeeded may have created a wrapper for the object, retry from the start.
3334 return ${className}::wrap(impl.get(), isolate);
3339 # FIXME: We need a better way of recovering the correct prototype chain
3340 # for every sort of object. For now, we special-case cross-origin visible
3341 # objects (i.e., those with CheckSecurity).
3342 if (IsVisibleAcrossOrigins($dataNode)) {
3343 push(@implContent, <<END);
3344 if (impl->frame()) {
3345 proxy = V8Proxy::retrieve(impl->frame());
3347 proxy->windowShell()->initContextIfNeeded();
3352 if (IsNodeSubType($dataNode) || IsVisibleAcrossOrigins($dataNode)) {
3353 push(@implContent, <<END);
3355 // Enter the node's context and create the wrapper in that context.
3356 v8::Handle<v8::Context> context;
3357 if (proxy && !proxy->matchesCurrentContext()) {
3358 // For performance, we enter the context only if the currently running context
3359 // is different from the context that we are about to enter.
3360 context = proxy->context();
3361 if (!context.IsEmpty())
3367 push(@implContent, <<END);
3368 wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl.get());
3370 if (IsNodeSubType($dataNode) || IsVisibleAcrossOrigins($dataNode)) {
3371 push(@implContent, <<END);
3372 // Exit the node's context if it was entered.
3373 if (!context.IsEmpty())
3378 push(@implContent, <<END);
3379 if (UNLIKELY(wrapper.IsEmpty()))
3383 my $hasEnabledPerContextFunctions = 0;
3384 foreach my $function (@{$dataNode->functions}) {
3385 if ($function->signature->extendedAttributes->{"V8EnabledPerContext"}) {
3386 $hasEnabledPerContextFunctions = 1;
3389 if ($hasEnabledPerContextFunctions) {
3390 push(@implContent, <<END);
3391 installPerContextProperties(wrapper, impl.get());
3395 push(@implContent, <<END);
3397 v8::Persistent<v8::Object> wrapperHandle = v8::Persistent<v8::Object>::New(wrapper);
3399 if (!hasDependentLifetime)
3400 wrapperHandle.MarkIndependent();
3402 if (IsNodeSubType($dataNode)) {
3403 push(@implContent, <<END);
3404 wrapperHandle.SetWrapperClassId(v8DOMSubtreeClassId);
3407 push(@implContent, <<END);
3408 V8DOMWrapper::setJSWrapperFor${domMapName}(impl, wrapperHandle, isolate);
3414 sub GetDomMapFunction
3416 my $dataNode = shift;
3417 my $interfaceName = shift;
3418 my $getIsolate = shift;
3420 return "get" . GetDomMapName($dataNode, $interfaceName) . "Map(" . $getIsolate . ")";
3425 my $dataNode = shift;
3428 return "ActiveDOMNode" if (IsNodeSubType($dataNode) && $dataNode->extendedAttributes->{"ActiveDOMObject"});
3429 return "DOMNode" if IsNodeSubType($dataNode);
3430 return "ActiveDOMObject" if $dataNode->extendedAttributes->{"ActiveDOMObject"};
3434 sub GetNativeTypeForConversions
3436 my $dataNode = shift;
3439 $type = $codeGenerator->GetSVGTypeNeedingTearOff($type) if $codeGenerator->IsSVGTypeNeedingTearOff($type);
3443 sub GenerateFunctionCallString()
3445 my $function = shift;
3446 my $numberOfParameters = shift;
3448 my $implClassName = shift;
3449 my %replacements = @_;
3451 my $name = $function->signature->name;
3452 my $returnType = GetTypeFromSignature($function->signature);
3453 my $nativeReturnType = GetNativeType($returnType, 0);
3456 my $isSVGTearOffType = ($codeGenerator->IsSVGTypeNeedingTearOff($returnType) and not $implClassName =~ /List$/);
3457 $nativeReturnType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType;
3459 if ($function->signature->extendedAttributes->{"ImplementedAs"}) {
3460 $name = $function->signature->extendedAttributes->{"ImplementedAs"};
3464 my $hasScriptState = 0;
3468 my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"};
3469 if ($implementedBy) {
3470 AddToImplIncludes("${implementedBy}.h");
3471 unshift(@arguments, "imp") if !$function->isStatic;
3472 $functionName = "${implementedBy}::${name}";
3473 } elsif ($function->isStatic) {
3474 $functionName = "${implClassName}::${name}";
3476 $functionName = "imp->${name}";
3479 my $callWith = $function->signature->extendedAttributes->{"CallWith"};
3480 my @callWithOutput = ();
3481 my @callWithArgs = GenerateCallWith($callWith, \@callWithOutput, $indent, 0, 1, $function);
3482 $result .= join("", @callWithOutput);
3483 unshift(@arguments, @callWithArgs);
3484 $index += @callWithArgs;
3485 $numberOfParameters += @callWithArgs;
3487 foreach my $parameter (@{$function->parameters}) {
3488 if ($index eq $numberOfParameters) {
3491 my $paramName = $parameter->name;
3492 my $paramType = $parameter->type;
3494 if ($replacements{$paramName}) {
3495 push @arguments, $replacements{$paramName};
3496 } elsif ($parameter->type eq "IDBKey" || $parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
3497 push @arguments, "$paramName.get()";
3498 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($parameter->type) and not $implClassName =~ /List$/) {
3499 push @arguments, "$paramName->propertyReference()";
3500 $result .= $indent . "if (!$paramName)\n";
3501 $result .= $indent . " return V8Proxy::setDOMException(WebCore::TYPE_MISMATCH_ERR, args.GetIsolate());\n";
3502 } elsif ($parameter->type eq "SVGMatrix" and $implClassName eq "SVGTransformList") {
3503 push @arguments, "$paramName.get()";
3505 push @arguments, $paramName;
3510 if (@{$function->raisesExceptions}) {
3511 push @arguments, "ec";
3514 my $functionString = "$functionName(" . join(", ", @arguments) . ")";
3516 my $return = "result";
3517 my $returnIsRef = IsRefPtrType($returnType);
3519 if ($returnType eq "void") {
3520 $result .= $indent . "$functionString;\n";
3521 } elsif ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState") or @{$function->raisesExceptions}) {
3522 $result .= $indent . $nativeReturnType . " result = $functionString;\n";
3524 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
3525 $return = $functionString;
3528 if ($implClassName eq "SVGTransformList" and IsRefPtrType($returnType)) {
3529 $return = "WTF::getPtr(" . $return . ")";
3533 if (@{$function->raisesExceptions}) {
3534 $result .= $indent . "if (UNLIKELY(ec))\n";
3535 $result .= $indent . " goto fail;\n";
3538 if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) {
3539 $result .= $indent . "if (state.hadException())\n";
3540 $result .= $indent . " return throwError(state.exception(), args.GetIsolate());\n"
3543 if ($isSVGTearOffType) {
3544 AddToImplIncludes("V8$returnType.h");
3545 AddToImplIncludes("SVGPropertyTearOff.h");
3546 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($returnType);
3547 $result .= $indent . "return toV8(WTF::getPtr(${svgNativeType}::create($return)), args.GetIsolate());\n";
3551 # If the implementing class is a POD type, commit changes
3552 if ($codeGenerator->IsSVGTypeNeedingTearOff($implClassName) and not $implClassName =~ /List$/) {
3553 $result .= $indent . "wrapper->commitChange();\n";
3556 $return .= ".release()" if ($returnIsRef);
3557 $result .= $indent . ReturnNativeToJSValue($function->signature, $return, "args.GetIsolate()") . ";\n";
3563 sub GetTypeFromSignature
3565 my $signature = shift;
3567 return $codeGenerator->StripModule($signature->type);
3571 sub GetNativeTypeFromSignature
3573 my $signature = shift;
3574 my $parameterIndex = shift;
3576 my $type = GetTypeFromSignature($signature);
3578 if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
3579 # Special-case index arguments because we need to check that they aren't < 0.
3583 $type = GetNativeType($type, $parameterIndex >= 0 ? 1 : 0);
3585 if ($parameterIndex >= 0 && $type eq "V8Parameter") {
3586 # FIXME: This implements [TreatNullAs=NullString] and [TreatUndefinedAs=NullString],
3587 # but the Web IDL spec requires [TreatNullAs=EmptyString] and [TreatUndefinedAs=EmptyString].
3589 if (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") and ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) {
3590 $mode = "WithUndefinedOrNullCheck";
3591 } elsif (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") or $signature->extendedAttributes->{"Reflect"}) {
3592 $mode = "WithNullCheck";
3594 # FIXME: Add the case for 'elsif ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString"))'.
3605 return 0 if $type eq "boolean";
3606 return 0 if $type eq "float";
3607 return 0 if $type eq "int";
3608 return 0 if $type eq "Date";
3609 return 0 if $type eq "DOMString";
3610 return 0 if $type eq "double";
3611 return 0 if $type eq "short";
3612 return 0 if $type eq "long";
3613 return 0 if $type eq "unsigned";
3614 return 0 if $type eq "unsigned long";
3615 return 0 if $type eq "unsigned short";
3623 my $isParameter = shift;
3625 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type);
3626 if ($svgNativeType) {
3627 if ($svgNativeType =~ /List$/) {
3628 return "${svgNativeType}*";
3630 return "RefPtr<${svgNativeType} >";
3634 my $sequenceType = $codeGenerator->GetSequenceType($type);
3635 return "Vector<${sequenceType}>" if $sequenceType;
3637 if ($type eq "float" or $type eq "double") {
3641 return "V8Parameter" if ($type eq "DOMString" or $type eq "DOMUserData") and $isParameter;
3642 return "int" if $type eq "int";
3643 return "int" if $type eq "short" or $type eq "unsigned short";
3644 return "unsigned" if $type eq "unsigned long";
3645 return "int" if $type eq "long";
3646 return "long long" if $type eq "long long";
3647 return "unsigned long long" if $type eq "unsigned long long";
3648 return "bool" if $type eq "boolean";
3649 return "String" if $type eq "DOMString";
3650 return "Range::CompareHow" if $type eq "CompareHow";
3651 return "DOMTimeStamp" if $type eq "DOMTimeStamp";
3652 return "unsigned" if $type eq "unsigned int";
3653 return "Node*" if $type eq "EventTarget" and $isParameter;
3654 return "double" if $type eq "Date";
3655 return "ScriptValue" if $type eq "DOMObject";
3656 return "Dictionary" if $type eq "Dictionary";
3658 return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack?
3661 return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
3663 return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
3665 return "RefPtr<IDBKey>" if $type eq "IDBKey";
3667 # necessary as resolvers could be constructed on fly.
3668 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
3670 return "RefPtr<DOMStringList>" if $type eq "DOMString[]";
3671 return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
3673 return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener";
3675 # FIXME: Support T[], T[]?, sequence<T> generically
3676 return "RefPtr<DOMStringList>" if $type eq "DOMStringList";
3678 # Default, assume native type is a pointer with same type name as idl type
3682 sub GetNativeTypeForCallbacks
3685 return "const String&" if $type eq "DOMString";
3686 return "SerializedScriptValue*" if $type eq "SerializedScriptValue";
3688 # Callbacks use raw pointers, so pass isParameter = 1
3689 return GetNativeType($type, 1);
3692 sub TranslateParameter
3694 my $signature = shift;
3696 # The IDL uses some pseudo-types which don't really exist.
3697 if ($signature->type eq "TimeoutHandler") {
3698 $signature->type("DOMString");
3702 sub TypeCanFailConversion
3704 my $signature = shift;
3706 my $type = GetTypeFromSignature($signature);
3708 AddToImplIncludes("ExceptionCode.h") if $type eq "Attr";
3709 return 1 if $type eq "Attr";
3710 return 1 if $type eq "VoidCallback";
3716 my $signature = shift;
3718 my $getIsolate = shift;
3720 my $type = GetTypeFromSignature($signature);
3722 return "$value" if $type eq "JSObject";
3723 return "$value->BooleanValue()" if $type eq "boolean";
3724 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
3726 return "toInt32($value)" if $type eq "long" or $type eq "short";
3727 return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsigned short";
3728 return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
3729 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
3730 return "toWebCoreDate($value)" if $type eq "Date";
3731 return "v8ValueToWebCoreDOMStringList($value)" if $type eq "DOMStringList";
3732 # FIXME: Add proper support for T[], T[]? and sequence<T>.
3733 return "v8ValueToWebCoreDOMStringList($value)" if $type eq "DOMString[]";
3735 if ($type eq "DOMString" or $type eq "DOMUserData") {
3739 if ($type eq "SerializedScriptValue") {
3740 AddToImplIncludes("SerializedScriptValue.h");
3741 return "SerializedScriptValue::create($value, $getIsolate)";
3744 if ($type eq "IDBKey") {
3745 AddToImplIncludes("IDBBindingUtilities.h");
3746 AddToImplIncludes("IDBKey.h");
3747 return "createIDBKeyFromValue($value)";
3750 if ($type eq "Dictionary") {
3751 AddToImplIncludes("Dictionary.h");
3755 if ($type eq "DOMObject") {
3756 AddToImplIncludes("ScriptValue.h");
3757 return "ScriptValue($value)";
3760 if ($type eq "NodeFilter") {
3761 return "V8DOMWrapper::wrapNativeNodeFilter($value)";
3764 if ($type eq "MediaQueryListListener") {
3765 AddToImplIncludes("MediaQueryListListener.h");
3766 return "MediaQueryListListener::create(" . $value . ")";
3769 # Default, assume autogenerated type conversion routines
3770 if ($type eq "EventTarget") {
3771 AddToImplIncludes("V8Node.h");
3773 # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
3774 return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3777 if ($type eq "XPathNSResolver") {
3778 return "V8DOMWrapper::getXPathNSResolver($value)";
3781 my $arrayType = $codeGenerator->GetArrayType($type);
3783 return "toNativeArray<$arrayType>($value)";
3786 my $sequenceType = $codeGenerator->GetSequenceType($type);
3787 if ($sequenceType) {
3788 return "toNativeArray<$sequenceType>($value)";
3791 AddIncludesForType($type);
3793 if (IsDOMNodeType($type)) {
3794 AddToImplIncludes("V8${type}.h");
3796 # Perform type checks on the parameter, if it is expected Node type,
3798 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3800 AddToImplIncludes("V8$type.h");
3802 # Perform type checks on the parameter, if it is expected Node type,
3804 return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
3811 return "V8Event.h" if $type eq "DOMTimeStamp";
3812 return "EventListener.h" if $type eq "EventListener";
3813 return "EventTarget.h" if $type eq "EventTarget";
3814 return "SerializedScriptValue.h" if $type eq "SerializedScriptValue";
3815 return "ScriptValue.h" if $type eq "DOMObject";
3816 return "V8DOMStringList.h" if $type eq "DOMString[]";
3817 return "V8${type}.h";
3820 sub CreateCustomSignature
3822 my $function = shift;
3823 my $count = @{$function->parameters};
3824 my $name = $function->signature->name;
3825 my $result = " const int ${name}Argc = ${count};\n" .
3826 " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { ";
3828 foreach my $parameter (@{$function->parameters}) {
3829 if ($first) { $first = 0; }
3830 else { $result .= ", "; }
3831 if (IsWrapperType($parameter->type)) {
3832 if ($parameter->type eq "XPathNSResolver") {
3833 # Special case for XPathNSResolver. All other browsers accepts a callable,
3834 # so, even though it's against IDL, accept objects here.
3835 $result .= "v8::Handle<v8::FunctionTemplate>()";
3837 my $type = $parameter->type;
3838 my $sequenceType = $codeGenerator->GetSequenceType($type);
3839 if ($sequenceType) {
3840 if ($codeGenerator->SkipIncludeHeader($sequenceType)) {
3841 $result .= "v8::Handle<v8::FunctionTemplate>()";
3844 AddToImplIncludes("$sequenceType.h");
3846 my $header = GetV8HeaderName($type);
3847 AddToImplIncludes($header);
3849 $result .= "V8${type}::GetRawTemplate()";
3852 $result .= "v8::Handle<v8::FunctionTemplate>()";
3856 $result .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n";
3861 sub RequiresCustomSignature
3863 my $function = shift;
3864 # No signature needed for Custom function
3865 if ($function->signature->extendedAttributes->{"Custom"} ||
3866 $function->signature->extendedAttributes->{"V8Custom"}) {
3869 # No signature needed for overloaded function
3870 if (@{$function->{overloads}} > 1) {
3873 if ($function->isStatic) {
3876 # Type checking is performed in the generated code
3877 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
3880 foreach my $parameter (@{$function->parameters}) {
3881 my $optional = $parameter->extendedAttributes->{"Optional"};
3882 if (($optional && $optional ne "DefaultIsUndefined" && $optional ne "DefaultIsNullString") || $parameter->extendedAttributes->{"Callback"}) {
3887 foreach my $parameter (@{$function->parameters}) {
3888 if (IsWrapperType($parameter->type)) {
3896 my %non_wrapper_types = (
3901 'DOMTimeStamp' => 1,
3904 'EventListener' => 1,
3908 'MediaQueryListListener' => 1,
3910 'SerializedScriptValue' => 1,
3918 'unsigned int' => 1,
3919 'unsigned long long' => 1,
3920 'unsigned long' => 1,
3921 'unsigned short' => 1
3927 my $type = $codeGenerator->StripModule(shift);
3928 return !($non_wrapper_types{$type});
3933 my $type = $codeGenerator->StripModule(shift);
3934 # FIXME: Add proper support for T[], T[]?, sequence<T>.
3935 return $type =~ m/\[\]$/;
3942 return 1 if $type eq 'Attr';
3943 return 1 if $type eq 'CDATASection';
3944 return 1 if $type eq 'Comment';
3945 return 1 if $type eq 'Document';
3946 return 1 if $type eq 'DocumentFragment';
3947 return 1 if $type eq 'DocumentType';
3948 return 1 if $type eq 'Element';
3949 return 1 if $type eq 'EntityReference';
3950 return 1 if $type eq 'HTMLCanvasElement';
3951 return 1 if $type eq 'HTMLDocument';
3952 return 1 if $type eq 'HTMLElement';
3953 return 1 if $type eq 'HTMLUnknownElement';
3954 return 1 if $type eq 'HTMLFormElement';
3955 return 1 if $type eq 'HTMLTableCaptionElement';
3956 return 1 if $type eq 'HTMLTableSectionElement';
3957 return 1 if $type eq 'Node';
3958 return 1 if $type eq 'ProcessingInstruction';
3959 return 1 if $type eq 'SVGElement';
3960 return 1 if $type eq 'SVGDocument';
3961 return 1 if $type eq 'SVGSVGElement';
3962 return 1 if $type eq 'SVGUseElement';
3963 return 1 if $type eq 'Text';
3971 my $signature = shift;
3973 my $getIsolate = shift;
3974 my $getIsolateArg = $getIsolate ? ", $getIsolate" : "";
3975 my $type = GetTypeFromSignature($signature);
3977 return ($getIsolate ? "v8Boolean($value, $getIsolate)" : "v8Boolean($value)") if $type eq "boolean";
3978 return "v8::Handle<v8::Value>()" if $type eq "void"; # equivalent to v8::Undefined()
3980 # HTML5 says that unsigned reflected attributes should be in the range
3981 # [0, 2^31). When a value isn't in this range, a default value (or 0)
3982 # should be returned instead.
3983 if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
3984 $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
3985 return "v8UnsignedInteger(std::max(0, " . $value . ")$getIsolateArg)";
3988 # For all the types where we use 'int' as the representation type,
3989 # we use v8Integer() which has a fast small integer conversion check.
3990 my $nativeType = GetNativeType($type);
3991 return "v8Integer($value$getIsolateArg)" if $nativeType eq "int";
3992 return "v8UnsignedInteger($value$getIsolateArg)" if $nativeType eq "unsigned";
3994 return "v8DateOrNull($value$getIsolateArg)" if $type eq "Date";
3995 # long long and unsigned long long are not representable in ECMAScript.
3996 return "v8::Number::New(static_cast<double>($value))" if $type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTimeStamp";
3997 return "v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type);
3998 return "$value.v8Value()" if $nativeType eq "ScriptValue";
4000 if ($codeGenerator->IsStringType($type)) {
4001 my $conv = $signature->extendedAttributes->{"TreatReturnedNullStringAs"};
4002 if (defined $conv) {
4003 return "v8StringOrNull($value$getIsolateArg)" if $conv eq "Null";
4004 return "v8StringOrUndefined($value$getIsolateArg)" if $conv eq "Undefined";
4005 return "v8StringOrFalse($value$getIsolateArg)" if $conv eq "False";
4007 die "Unknown value for TreatReturnedNullStringAs extended attribute";
4009 return "v8String($value$getIsolateArg)";
4012 my $arrayType = $codeGenerator->GetArrayType($type);
4014 if ($type eq "DOMString[]") {
4015 AddToImplIncludes("V8DOMStringList.h");
4016 AddToImplIncludes("DOMStringList.h");
4017 } elsif (!$codeGenerator->SkipIncludeHeader($arrayType)) {
4018 AddToImplIncludes("V8$arrayType.h");
4019 AddToImplIncludes("$arrayType.h");
4021 return "v8Array($value$getIsolateArg)";
4024 my $sequenceType = $codeGenerator->GetSequenceType($type);
4025 if ($sequenceType) {
4026 if (!$codeGenerator->SkipIncludeHeader($sequenceType)) {
4027 AddToImplIncludes("V8$sequenceType.h");
4028 AddToImplIncludes("$sequenceType.h");
4030 return "v8Array($value, $getIsolate)";
4033 AddIncludesForType($type);
4035 # special case for non-DOM node interfaces
4036 if (IsDOMNodeType($type)) {
4037 return "toV8(${value}" . ($signature->extendedAttributes->{"ReturnNewObject"} ? "$getIsolateArg, true)" : "$getIsolateArg)");
4040 if ($type eq "EventTarget") {
4041 return "V8DOMWrapper::convertEventTargetToV8Object($value$getIsolateArg)";
4044 if ($type eq "EventListener") {
4045 AddToImplIncludes("V8AbstractEventListener.h");
4046 return "${value} ? v8::Handle<v8::Value>(static_cast<V8AbstractEventListener*>(${value})->getListenerObject(imp->scriptExecutionContext())) : v8::Handle<v8::Value>(" . ($getIsolate ? "v8::Null($getIsolate)" : "v8::Null()") . ")";
4049 if ($type eq "SerializedScriptValue") {
4050 AddToImplIncludes("$type.h");
4051 return "$value ? $value->deserialize() : v8::Handle<v8::Value>(" . ($getIsolate ? "v8::Null($getIsolate)" : "v8::Null()") . ")";
4054 AddToImplIncludes("wtf/RefCounted.h");
4055 AddToImplIncludes("wtf/RefPtr.h");
4056 AddToImplIncludes("wtf/GetPtr.h");
4058 return "toV8($value$getIsolateArg)";
4061 sub ReturnNativeToJSValue
4063 return "return " . NativeToJSValue(@_);
4070 my $dataNode = shift;
4072 my $name = $dataNode->name;
4073 my $prefix = FileNamePrefix;
4074 my $headerFileName = "$outputHeadersDir/$prefix$name.h";
4075 my $implFileName = "$outputDir/$prefix$name.cpp";
4077 # Update a .cpp file if the contents are changed.
4078 my $contents = join "", @implContentHeader, @implFixedHeader;
4081 my %implIncludeConditions = ();
4082 foreach my $include (keys %implIncludes) {
4083 my $condition = $implIncludes{$include};
4084 my $checkType = $include;
4085 $checkType =~ s/\.h//;
4086 next if $codeGenerator->IsSVGAnimatedType($checkType);
4088 if ($include =~ /wtf/) {
4089 $include = "\<$include\>";
4091 $include = "\"$include\"";
4094 if ($condition eq 1) {
4095 push @includes, $include;
4097 push @{$implIncludeConditions{$condition}}, $include;
4100 foreach my $include (sort @includes) {
4101 $contents .= "#include $include\n";
4103 foreach my $condition (sort keys %implIncludeConditions) {
4104 $contents .= "\n#if " . $codeGenerator->GenerateConditionalStringFromAttributeValue($condition) . "\n";
4105 foreach my $include (sort @{$implIncludeConditions{$condition}}) {
4106 $contents .= "#include $include\n";
4108 $contents .= "#endif\n";
4112 $contents .= join "", @implContentDecls, @implContent;
4113 $codeGenerator->UpdateFile($implFileName, $contents);
4116 @implFixedHeader = ();
4117 @implContentDecls = ();
4120 # Update a .h file if the contents are changed.
4121 $contents = join "", @headerContent;
4122 $codeGenerator->UpdateFile($headerFileName, $contents);
4124 @headerContent = ();
4127 sub GetCallbackClassName
4129 my $interfaceName = shift;
4131 return "V8CustomVoidCallback" if $interfaceName eq "VoidCallback";
4132 return "V8$interfaceName";
4135 sub ConvertToV8Parameter
4137 my $signature = shift;
4138 my $nativeType = shift;
4139 my $variableName = shift;
4143 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8Parameter/;
4144 if ($signature->type eq "DOMString") {
4145 AddToImplIncludes("V8BindingMacros.h");
4146 my $macro = "STRING_TO_V8PARAMETER_EXCEPTION_BLOCK";
4147 $macro .= "_$suffix" if $suffix;
4148 return "$macro($nativeType, $variableName, $value);"
4150 # Don't know how to properly check for conversion exceptions when $parameter->type is "DOMUserData"
4151 return "$nativeType $variableName($value, true);";
4155 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
4156 sub GetRuntimeEnableFunctionName
4158 my $signature = shift;
4160 # If a parameter is given (e.g. "V8EnabledAtRuntime=FeatureName") return the RuntimeEnabledFeatures::{FeatureName}Enabled() method.
4161 return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->extendedAttributes->{"V8EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"V8EnabledAtRuntime"} && $signature->extendedAttributes->{"V8EnabledAtRuntime"} ne "VALUE_IS_MISSING");
4163 # Otherwise return a function named RuntimeEnabledFeatures::{methodName}Enabled().
4164 return "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($signature->name) . "Enabled";
4167 sub GetContextEnableFunction
4169 my $signature = shift;
4171 # If a parameter is given (e.g. "V8EnabledPerContext=FeatureName") return the {FeatureName}Allowed() method.
4172 if ($signature->extendedAttributes->{"V8EnabledPerContext"} && $signature->extendedAttributes->{"V8EnabledPerContext"} ne "VALUE_IS_MISSING") {
4173 return "ContextFeatures::" . $codeGenerator->WK_lcfirst($signature->extendedAttributes->{"V8EnabledPerContext"}) . "Enabled";
4176 # Or it fallbacks to the attribute name if the parameter value is missing.
4177 my $attributeName = $signature->name;
4178 return "ContextFeatures::" . $codeGenerator->WK_lcfirst($attributeName) . "Enabled";
4181 sub GetPassRefPtrType
4183 my $className = shift;
4185 my $angleBracketSpace = $className =~ />$/ ? " " : "";
4186 return "PassRefPtr<${className}${angleBracketSpace}>";