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)
10 # Copyright (C) 2012 Ericsson AB. All rights reserved.
12 # This library is free software; you can redistribute it and/or
13 # modify it under the terms of the GNU Library General Public
14 # License as published by the Free Software Foundation; either
15 # version 2 of the License, or (at your option) any later version.
17 # This library is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 # Library General Public License for more details.
22 # You should have received a copy of the GNU Library General Public License
23 # along with this library; see the file COPYING.LIB. If not, write to
24 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 # Boston, MA 02111-1307, USA.
28 package CodeGeneratorV8;
32 use constant FileNamePrefix => "V8";
37 my @headerContent = ();
38 my @implContentHeader = ();
40 my @implContentInternals = ();
41 my %implIncludes = ();
42 my %headerIncludes = ();
45 my $headerTemplate = << "EOF";
47 This file is part of the WebKit open source project.
48 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
50 This library is free software; you can redistribute it and/or
51 modify it under the terms of the GNU Library General Public
52 License as published by the Free Software Foundation; either
53 version 2 of the License, or (at your option) any later version.
55 This library is distributed in the hope that it will be useful,
56 but WITHOUT ANY WARRANTY; without even the implied warranty of
57 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
58 Library General Public License for more details.
60 You should have received a copy of the GNU Library General Public License
61 along with this library; see the file COPYING.LIB. If not, write to
62 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
63 Boston, MA 02111-1307, USA.
73 $codeGenerator = shift;
75 bless($reference, $object);
82 my $interface = shift;
84 # Start actual generation
85 if ($interface->extendedAttributes->{"Callback"}) {
86 $object->GenerateCallbackHeader($interface);
87 $object->GenerateCallbackImplementation($interface);
89 $object->GenerateHeader($interface);
90 $object->GenerateImplementation($interface);
97 my $conditional = shift;
99 if (not $conditional) {
100 $implIncludes{$header} = 1;
101 } elsif (not exists($implIncludes{$header})) {
102 $implIncludes{$header} = $conditional;
104 my $oldValue = $implIncludes{$header};
105 if ($oldValue ne 1) {
107 $newValue{$conditional} = 1;
108 foreach my $condition (split(/\|/, $oldValue)) {
109 $newValue{$condition} = 1;
111 $implIncludes{$header} = join("|", sort keys %newValue);
116 sub AddIncludesForType
120 # When we're finished with the one-file-per-class
121 # reorganization, we won't need these special cases.
122 if ($codeGenerator->IsTypedArrayType($type)) {
123 AddToImplIncludes("wtf/${type}.h");
125 if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->IsStringType($type) and !$codeGenerator->SkipIncludeHeader($type) and $type ne "Date") {
126 # default, include the same named file
127 AddToImplIncludes(GetV8HeaderName(${type}));
129 if ($type =~ /SVGPathSeg/) {
130 my $joinedName = $type;
131 $joinedName =~ s/Abs|Rel//;
132 AddToImplIncludes("${joinedName}.h");
136 # additional includes (things needed to compile the bindings but not the header)
138 if ($type eq "CanvasRenderingContext2D") {
139 AddToImplIncludes("CanvasGradient.h");
140 AddToImplIncludes("CanvasPattern.h");
141 AddToImplIncludes("CanvasStyle.h");
144 if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") {
145 AddToImplIncludes("wtf/text/WTFString.h");
148 if ($type eq "CSSStyleSheet" or $type eq "StyleSheet") {
149 AddToImplIncludes("CSSImportRule.h");
152 if ($type eq "CSSStyleDeclaration") {
153 AddToImplIncludes("StylePropertySet.h");
156 if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") {
157 # So we can get String -> AtomicString conversion for namedItem().
158 AddToImplIncludes("wtf/text/AtomicString.h");
162 sub NeedsCustomOpaqueRootForGC
164 my $interface = shift;
165 return GetGenerateIsReachable($interface) || GetCustomIsReachable($interface);
168 sub GetGenerateIsReachable
170 my $interface = shift;
171 return $interface->extendedAttributes->{"GenerateIsReachable"} || $interface->extendedAttributes->{"V8GenerateIsReachable"} || ""
174 sub GetCustomIsReachable
176 my $interface = shift;
177 return $interface->extendedAttributes->{"CustomIsReachable"} || $interface->extendedAttributes->{"V8CustomIsReachable"};
180 sub GenerateOpaqueRootForGC
182 my $interface = shift;
183 my $interfaceName = $interface->name;
185 if (GetCustomIsReachable($interface)) {
189 push(@implContent, <<END);
190 void* V8${interfaceName}::opaqueRootForGC(void* object, v8::Persistent<v8::Object> wrapper, v8::Isolate* isolate)
192 ASSERT(!wrapper.IsIndependent(isolate));
193 ${interfaceName}* impl = static_cast<${interfaceName}*>(object);
195 if (GetGenerateIsReachable($interface) eq "ImplDocument" ||
196 GetGenerateIsReachable($interface) eq "ImplElementRoot" ||
197 GetGenerateIsReachable($interface) eq "ImplOwnerRoot" ||
198 GetGenerateIsReachable($interface) eq "ImplOwnerNodeRoot") {
200 $implIncludes{"V8GCController.h"} = 1;
203 $methodName = "document" if (GetGenerateIsReachable($interface) eq "ImplDocument");
204 $methodName = "element" if (GetGenerateIsReachable($interface) eq "ImplElementRoot");
205 $methodName = "owner" if (GetGenerateIsReachable($interface) eq "ImplOwnerRoot");
206 $methodName = "ownerNode" if (GetGenerateIsReachable($interface) eq "ImplOwnerNodeRoot");
208 push(@implContent, <<END);
209 if (Node* owner = impl->${methodName}())
210 return V8GCController::opaqueRootForGC(owner, isolate);
214 push(@implContent, <<END);
221 sub GetSVGPropertyTypes
223 my $implType = shift;
226 my $svgListPropertyType;
229 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
231 $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType);
232 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
234 # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType>
235 $svgNativeType = "$svgNativeType ";
237 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType);
238 if ($svgNativeType =~ /SVGPropertyTearOff/) {
239 $svgPropertyType = $svgWrappedNativeType;
240 AddToImplIncludes("SVGAnimatedPropertyTearOff.h");
241 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) {
242 $svgListPropertyType = $svgWrappedNativeType;
243 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
244 $headerIncludes{"SVGStaticListPropertyTearOff.h"} = 1;
245 } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) {
246 $svgListPropertyType = $svgWrappedNativeType;
247 $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1;
248 $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1;
249 } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
250 $svgListPropertyType = $svgWrappedNativeType;
251 $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1;
254 if ($svgPropertyType) {
255 $svgPropertyType = "SVGPoint" if $svgPropertyType eq "FloatPoint";
258 return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
264 my $interface = shift;
266 my $interfaceName = $interface->name;
267 my $v8InterfaceName = "V8$interfaceName";
269 # Copy contents of parent interfaces except the first parent.
271 $codeGenerator->AddMethodsConstantsAndAttributesFromParentInterfaces($interface, \@parents, 1);
272 $codeGenerator->LinkOverloadedFunctions($interface);
274 # Ensure the IsDOMNodeType function is in sync.
275 die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMNodeType($interfaceName) != $codeGenerator->InheritsInterface($interface, "Node");
277 my $hasDependentLifetime = $interface->extendedAttributes->{"V8DependentLifetime"} || $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject") || GetGenerateIsReachable($interface) || $v8InterfaceName =~ /SVG/;
278 if (!$hasDependentLifetime) {
279 foreach (@{$interface->parents}) {
281 $headerIncludes{"V8${parent}.h"} = 1;
285 # - Add default header template
286 push(@headerContent, GenerateHeaderContentHeader($interface));
288 $headerIncludes{"wtf/text/StringHash.h"} = 1;
289 $headerIncludes{"WrapperTypeInfo.h"} = 1;
290 $headerIncludes{"V8Binding.h"} = 1;
291 $headerIncludes{"V8DOMWrapper.h"} = 1;
292 $headerIncludes{"wtf/HashMap.h"} = 1;
293 $headerIncludes{"v8.h"} = 1;
295 my $headerClassInclude = GetHeaderClassInclude($interfaceName);
296 $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
298 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
300 foreach my $headerInclude (sort keys(%headerIncludes)) {
301 if ($headerInclude =~ /wtf|v8\.h/) {
302 push(@headerContent, "#include \<${headerInclude}\>\n");
304 push(@headerContent, "#include \"${headerInclude}\"\n");
308 push(@headerContent, "\nnamespace WebCore {\n");
309 push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
310 if ($svgNativeType) {
311 if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
312 push(@headerContent, "\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
314 push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
318 push(@headerContent, "\n");
319 push(@headerContent, "class FloatRect;\n") if $svgPropertyType && $svgPropertyType eq "FloatRect";
320 push(@headerContent, "class Dictionary;\n") if $codeGenerator->IsConstructorTemplate($interface, "Event");
322 my $nativeType = GetNativeTypeForConversions($interface);
323 if ($interface->extendedAttributes->{"NamedConstructor"}) {
324 push(@headerContent, <<END);
325 class V8${nativeType}Constructor {
327 static v8::Persistent<v8::FunctionTemplate> GetTemplate(v8::Isolate*);
328 static WrapperTypeInfo info;
334 push(@headerContent, "class $v8InterfaceName {\n");
335 push(@headerContent, "public:\n");
337 push(@headerContent, " static const bool hasDependentLifetime = ");
338 if ($hasDependentLifetime) {
339 push(@headerContent, "true;\n");
340 } elsif (@{$interface->parents}) {
341 # Even if this type doesn't have the V8DependentLifetime attribute its parents may.
342 # Let the compiler statically determine this for us.
344 foreach (@{$interface->parents}) {
346 $headerIncludes{"V8${parent}.h"} = 1;
347 push(@headerContent, "${separator}V8${parent}::hasDependentLifetime");
350 push(@headerContent, ";\n");
352 push(@headerContent, "false;\n");
355 my $fromFunctionOpening = "";
356 my $fromFunctionClosing = "";
357 if ($interface->extendedAttributes->{"V8WrapAsFunction"}) {
358 $fromFunctionOpening = "V8DOMWrapper::fromFunction(";
359 $fromFunctionClosing = ")";
362 push(@headerContent, <<END);
363 static bool HasInstance(v8::Handle<v8::Value>, v8::Isolate*);
364 static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(v8::Isolate*);
365 static v8::Persistent<v8::FunctionTemplate> GetTemplate(v8::Isolate*);
366 static ${nativeType}* toNative(v8::Handle<v8::Object> object)
368 return reinterpret_cast<${nativeType}*>(${fromFunctionOpening}object${fromFunctionClosing}->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex));
370 static void derefObject(void*);
371 static WrapperTypeInfo info;
374 if (NeedsCustomOpaqueRootForGC($interface)) {
375 push(@headerContent, " static void* opaqueRootForGC(void*, v8::Persistent<v8::Object>, v8::Isolate*);\n");
378 if ($codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
379 push(@headerContent, " static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
382 if ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
383 push(@headerContent, " static EventTarget* toEventTarget(v8::Handle<v8::Object>);\n");
386 if ($interfaceName eq "DOMWindow") {
387 push(@headerContent, <<END);
388 static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate(v8::Isolate*);
392 if ($interfaceName eq "HTMLDocument") {
393 push(@headerContent, <<END);
394 static v8::Local<v8::Object> wrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl, v8::Isolate*);
398 my @enabledPerContextFunctions;
399 foreach my $function (@{$interface->functions}) {
400 my $name = $function->signature->name;
401 my $attrExt = $function->signature->extendedAttributes;
403 if (HasCustomMethod($attrExt) && !$attrExt->{"ImplementedBy"} && $function->{overloadIndex} == 1) {
404 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
405 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
406 push(@headerContent, <<END);
407 static v8::Handle<v8::Value> ${name}MethodCustom(const v8::Arguments&);
409 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
411 if ($attrExt->{"V8EnabledPerContext"}) {
412 push(@enabledPerContextFunctions, $function);
416 if (IsConstructable($interface)) {
417 push(@headerContent, " static v8::Handle<v8::Value> constructorCallback(const v8::Arguments&);\n");
420 if (HasCustomConstructor($interface)) {
421 push(@headerContent, " static v8::Handle<v8::Value> constructorCustom(const v8::Arguments&);\n");
424 my @enabledPerContextAttributes;
425 foreach my $attribute (@{$interface->attributes}) {
426 my $name = $attribute->signature->name;
427 my $attrExt = $attribute->signature->extendedAttributes;
428 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
429 if (HasCustomGetter($attrExt) && !$attrExt->{"ImplementedBy"}) {
430 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
431 push(@headerContent, <<END);
432 static v8::Handle<v8::Value> ${name}AttrGetterCustom(v8::Local<v8::String> name, const v8::AccessorInfo&);
434 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
436 if (HasCustomSetter($attrExt) && !$attrExt->{"ImplementedBy"}) {
437 push(@headerContent, "#if ${conditionalString}\n") if $conditionalString;
438 push(@headerContent, <<END);
439 static void ${name}AttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&);
441 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
443 if ($attrExt->{"V8EnabledPerContext"}) {
444 push(@enabledPerContextAttributes, $attribute);
448 GenerateHeaderNamedAndIndexedPropertyAccessors($interface);
449 GenerateHeaderCustomCall($interface);
450 GenerateHeaderCustomInternalFieldIndices($interface);
452 if ($interface->name eq "DOMWindow") {
453 push(@headerContent, <<END);
454 static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
455 static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
459 if (@enabledPerContextAttributes) {
460 push(@headerContent, <<END);
461 static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*);
464 push(@headerContent, <<END);
465 static void installPerContextProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*) { }
469 if (@enabledPerContextFunctions) {
470 push(@headerContent, <<END);
471 static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*);
474 push(@headerContent, <<END);
475 static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*) { }
479 if ($interfaceName eq "HTMLElement") {
480 push(@headerContent, <<END);
481 friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
482 friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
484 } elsif ($interfaceName eq "SVGElement") {
485 push(@headerContent, <<END);
486 friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
487 friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
488 friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
490 } elsif ($interfaceName eq "HTMLUnknownElement") {
491 push(@headerContent, <<END);
492 friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
494 } elsif ($interfaceName eq "Element") {
495 push(@headerContent, <<END);
496 // This is a performance optimization hack. See V8Element::wrap.
497 friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
501 push(@headerContent, <<END);
505 my $noToV8 = $interface->extendedAttributes->{"SuppressToJSObject"};
506 my $noWrap = $interface->extendedAttributes->{"V8NoWrapperCache"} || $noToV8;
508 my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
509 push(@headerContent, <<END);
510 friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
511 static v8::Handle<v8::Object> createWrapper(${createWrapperArgumentType}, v8::Handle<v8::Object> creationContext, v8::Isolate*);
515 push(@headerContent, <<END);
520 my $customWrap = !!($interface->extendedAttributes->{"CustomToJSObject"} or $interface->extendedAttributes->{"V8CustomToJSObject"});
522 die "Can't suppress toV8 for subclass\n" if @parents;
524 die "Must have custom toV8\n" if !$customWrap;
525 push(@headerContent, <<END);
527 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
529 template<class HolderContainer, class Wrappable>
530 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const HolderContainer& container, Wrappable*)
532 return toV8(impl, container.Holder(), container.GetIsolate());
537 my $createWrapperCall = $customWrap ? "${v8InterfaceName}::wrap" : "${v8InterfaceName}::createWrapper";
538 my $returningWrapper = $interface->extendedAttributes->{"V8WrapAsFunction"} ? "V8DOMWrapper::toFunction(wrapper)" : "wrapper";
539 my $returningCreatedWrapperOpening = $interface->extendedAttributes->{"V8WrapAsFunction"} ? "V8DOMWrapper::toFunction(" : "";
540 my $returningCreatedWrapperClosing = $interface->extendedAttributes->{"V8WrapAsFunction"} ? ", impl->name(), isolate)" : "";
543 push(@headerContent, <<END);
545 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*);
548 push(@headerContent, <<END);
550 inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
553 ASSERT(DOMDataStore::getWrapper(impl, isolate).IsEmpty());
554 return ${returningCreatedWrapperOpening}$createWrapperCall(impl, creationContext, isolate)${returningCreatedWrapperClosing};
559 push(@headerContent, <<END);
561 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
564 return v8NullWithCheck(isolate);
565 v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper(impl, isolate);
566 if (!wrapper.IsEmpty())
567 return $returningWrapper;
568 return wrap(impl, creationContext, isolate);
571 template<class HolderContainer, class Wrappable>
572 inline v8::Handle<v8::Value> toV8Fast(${nativeType}* impl, const HolderContainer& container, Wrappable* wrappable)
575 return v8Null(container.GetIsolate());
576 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperFast(impl, container, wrappable);
577 if (!wrapper.IsEmpty())
578 return $returningWrapper;
579 return wrap(impl, container.Holder(), container.GetIsolate());
584 push(@headerContent, <<END);
586 template<class HolderContainer, class Wrappable>
587 inline v8::Handle<v8::Value> toV8Fast(PassRefPtr< ${nativeType} > impl, const HolderContainer& container, Wrappable* wrappable)
589 return toV8Fast(impl.get(), container, wrappable);
592 inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
594 return toV8(impl.get(), creationContext, isolate);
598 if ($codeGenerator->IsConstructorTemplate($interface, "Event")) {
599 push(@headerContent, "\nbool fill${interfaceName}Init(${interfaceName}Init&, const Dictionary&);\n");
602 push(@headerContent, "\n}\n\n");
603 push(@headerContent, "#endif // $v8InterfaceName" . "_h\n");
605 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
606 push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
609 sub GetInternalFields
611 my $interface = shift;
613 my @customInternalFields = ();
614 # Event listeners on DOM nodes are explicitly supported in the GC controller.
615 if (!$codeGenerator->InheritsInterface($interface, "Node") &&
616 $codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
617 push(@customInternalFields, "eventListenerCacheIndex");
619 return @customInternalFields;
622 sub GetHeaderClassInclude
624 my $v8InterfaceName = shift;
625 if ($v8InterfaceName =~ /SVGPathSeg/) {
626 $v8InterfaceName =~ s/Abs|Rel//;
628 return "wtf/${v8InterfaceName}.h" if $codeGenerator->IsTypedArrayType($v8InterfaceName);
629 return "" if ($codeGenerator->SkipIncludeHeader($v8InterfaceName));
630 return "${v8InterfaceName}.h";
633 sub GenerateHeaderCustomInternalFieldIndices
635 my $interface = shift;
636 my @customInternalFields = GetInternalFields($interface);
637 my $customFieldCounter = 0;
638 foreach my $customInternalField (@customInternalFields) {
639 push(@headerContent, <<END);
640 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
642 $customFieldCounter++;
644 push(@headerContent, <<END);
645 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
649 my %indexerSpecialCases = (
651 "HTMLAppletElement" => 1,
652 "HTMLEmbedElement" => 1,
653 "HTMLObjectElement" => 1
656 sub GenerateHeaderNamedAndIndexedPropertyAccessors
658 my $interface = shift;
659 my $interfaceName = $interface->name;
660 my $hasCustomIndexedGetter = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
661 my $hasCustomIndexedSetter = $interface->extendedAttributes->{"CustomIndexedSetter"} && !$interface->extendedAttributes->{"NumericIndexedGetter"};
662 my $hasCustomNamedGetter = $interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
663 my $hasCustomNamedSetter = $interface->extendedAttributes->{"CustomNamedSetter"};
664 my $hasCustomDeleters = $interface->extendedAttributes->{"CustomDeleteProperty"};
665 my $hasCustomEnumerator = $interface->extendedAttributes->{"CustomEnumerateProperty"};
666 if ($interfaceName eq "HTMLOptionsCollection") {
667 $interfaceName = "HTMLCollection";
668 $hasCustomIndexedGetter = 1;
669 $hasCustomNamedGetter = 1;
671 if ($interfaceName eq "DOMWindow") {
672 $hasCustomDeleters = 0;
673 $hasCustomEnumerator = 0;
675 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
676 $hasCustomNamedGetter = 1;
678 if ($interfaceName eq "HTMLDocument") {
679 $hasCustomNamedGetter = 0;
680 $hasCustomIndexedGetter = 0;
682 my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName};
684 if ($hasCustomIndexedGetter || $isIndexerSpecialCase) {
685 push(@headerContent, <<END);
686 static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t, const v8::AccessorInfo&);
690 if ($isIndexerSpecialCase || $hasCustomIndexedSetter) {
691 push(@headerContent, <<END);
692 static v8::Handle<v8::Value> indexedPropertySetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
695 if ($hasCustomDeleters) {
696 push(@headerContent, <<END);
697 static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t, const v8::AccessorInfo&);
700 if ($hasCustomNamedGetter) {
701 push(@headerContent, <<END);
702 static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String>, const v8::AccessorInfo&);
705 if ($hasCustomNamedSetter) {
706 push(@headerContent, <<END);
707 static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&);
710 if ($hasCustomDeleters) {
711 push(@headerContent, <<END);
712 static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&);
715 if ($hasCustomEnumerator) {
716 push(@headerContent, <<END);
717 static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo&);
718 static v8::Handle<v8::Integer> namedPropertyQuery(v8::Local<v8::String>, const v8::AccessorInfo&);
723 sub GenerateHeaderCustomCall
725 my $interface = shift;
727 if ($interface->extendedAttributes->{"CustomCall"}) {
728 push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n");
730 if ($interface->name eq "Location") {
731 push(@headerContent, " static v8::Handle<v8::Value> assignAttrGetterCustom(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
732 push(@headerContent, " static v8::Handle<v8::Value> reloadAttrGetterCustom(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
733 push(@headerContent, " static v8::Handle<v8::Value> replaceAttrGetterCustom(v8::Local<v8::String> name, const v8::AccessorInfo&);\n");
739 my $interface = shift;
741 return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"V8CustomConstructor"} || $interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"ConstructorTemplate"};
744 sub HasCustomConstructor
746 my $interface = shift;
748 return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"V8CustomConstructor"};
754 return $attrExt->{"Custom"} || $attrExt->{"V8Custom"} || $attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"};
760 return $attrExt->{"Custom"} || $attrExt->{"V8Custom"} || $attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"};
766 return $attrExt->{"Custom"} || $attrExt->{"V8Custom"};
771 my $attribute = shift;
772 my $attrExt = $attribute->signature->extendedAttributes;
773 return ($attribute->type =~ /readonly/ || $attrExt->{"V8ReadOnly"}) && !$attrExt->{"Replaceable"};
776 sub GenerateDomainSafeFunctionGetter
778 my $function = shift;
779 my $interfaceName = shift;
781 my $v8InterfaceName = "V8" . $interfaceName;
782 my $funcName = $function->signature->name;
784 my $signature = "v8::Signature::New(" . $v8InterfaceName . "::GetRawTemplate(info.GetIsolate()))";
785 if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) {
786 $signature = "v8::Local<v8::Signature>()";
789 my $newTemplateString = "v8::FunctionTemplate::New(${interfaceName}V8Internal::${funcName}MethodCallback, v8Undefined(), $signature)";
791 AddToImplIncludes("Frame.h");
792 push(@implContentInternals, <<END);
793 static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
795 static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(info.GetIsolate(), $newTemplateString);
796 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8InterfaceName}::GetTemplate(info.GetIsolate()));
797 if (holder.IsEmpty()) {
798 // can only reach here by 'object.__proto__.func', and it should passed
799 // domain security check already
800 return privateTemplate->GetFunction();
802 ${interfaceName}* imp = ${v8InterfaceName}::toNative(holder);
803 if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame(), DoNotReportSecurityError)) {
804 static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(info.GetIsolate(), $newTemplateString);
805 return sharedTemplate->GetFunction();
808 v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(name);
809 if (!hiddenValue.IsEmpty())
812 return privateTemplate->GetFunction();
815 static v8::Handle<v8::Value> ${funcName}AttrGetterCallback(v8::Local<v8::String> name, const v8::AccessorInfo& info)
817 return ${interfaceName}V8Internal::${funcName}AttrGetter(name, info);
823 sub GenerateDomainSafeFunctionSetter
825 my $interfaceName = shift;
826 my $v8InterfaceName = "V8" . $interfaceName;
828 push(@implContentInternals, <<END);
829 static void ${interfaceName}DomainSafeFunctionSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
831 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8InterfaceName}::GetTemplate(info.GetIsolate()));
832 if (holder.IsEmpty())
834 ${interfaceName}* imp = ${v8InterfaceName}::toNative(holder);
835 if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
838 info.This()->SetHiddenValue(name, value);
844 sub GenerateConstructorGetter
846 my $interface = shift;
847 my $interfaceName = $interface->name;
849 push(@implContentInternals, <<END);
850 static v8::Handle<v8::Value> ${interfaceName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
852 v8::Handle<v8::Value> data = info.Data();
853 ASSERT(data->IsExternal());
854 V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext());
856 return v8Undefined();
857 return perContextData->constructorForType(WrapperTypeInfo::unwrap(data));
862 sub GenerateFeatureObservation
864 my $measureAs = shift;
867 AddToImplIncludes("FeatureObserver.h");
868 return " FeatureObserver::observe(activeDOMWindow(BindingState::instance()), FeatureObserver::${measureAs});\n";
874 sub GenerateNormalAttrGetterCallback
876 my $attribute = shift;
877 my $interface = shift;
879 my $interfaceName = $interface->name;
880 my $v8InterfaceName = "V8$interfaceName";
881 my $attrExt = $attribute->signature->extendedAttributes;
882 my $attrName = $attribute->signature->name;
884 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
885 push(@implContentInternals, "#if ${conditionalString}\n\n") if $conditionalString;
887 push(@implContentInternals, "static v8::Handle<v8::Value> ${attrName}AttrGetterCallback(v8::Local<v8::String> name, const v8::AccessorInfo& info)\n");
888 push(@implContentInternals, "{\n");
889 push(@implContentInternals, GenerateFeatureObservation($attrExt->{"V8MeasureAs"}));
890 if (HasCustomGetter($attrExt)) {
891 push(@implContentInternals, " return ${v8InterfaceName}::${attrName}AttrGetterCustom(name, info);\n");
893 push(@implContentInternals, " return ${interfaceName}V8Internal::${attrName}AttrGetter(name, info);\n");
895 push(@implContentInternals, "}\n\n");
896 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
899 sub GenerateNormalAttrGetter
901 my $attribute = shift;
902 my $interface = shift;
904 my $interfaceName = $interface->name;
905 my $v8InterfaceName = "V8$interfaceName";
906 my $attrExt = $attribute->signature->extendedAttributes;
907 my $attrName = $attribute->signature->name;
908 my $attrType = $attribute->signature->type;
910 if (HasCustomGetter($attrExt)) {
914 $codeGenerator->AssertNotSequenceType($attrType);
915 my $getterStringUsesImp = $interfaceName ne "SVGNumber";
916 my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
917 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName);
919 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
920 push(@implContentInternals, "#if ${conditionalString}\n\n") if $conditionalString;
921 push(@implContentInternals, <<END);
922 static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
925 if ($svgNativeType) {
926 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
927 if ($svgWrappedNativeType =~ /List/) {
928 push(@implContentInternals, <<END);
929 $svgNativeType* imp = ${v8InterfaceName}::toNative(info.Holder());
932 push(@implContentInternals, <<END);
933 $svgNativeType* wrapper = ${v8InterfaceName}::toNative(info.Holder());
934 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
936 if ($getterStringUsesImp) {
937 push(@implContentInternals, <<END);
938 $svgWrappedNativeType* imp = &impInstance;
942 } elsif ($attrExt->{"V8OnProto"} || $attrExt->{"V8Unforgeable"}) {
943 if ($interfaceName eq "DOMWindow") {
944 push(@implContentInternals, <<END);
945 v8::Handle<v8::Object> holder = info.Holder();
948 # perform lookup first
949 push(@implContentInternals, <<END);
950 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8InterfaceName}::GetTemplate(info.GetIsolate()));
951 if (holder.IsEmpty())
952 return v8Undefined();
955 push(@implContentInternals, <<END);
956 ${interfaceName}* imp = ${v8InterfaceName}::toNative(holder);
959 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
960 my $url = $attribute->signature->extendedAttributes->{"URL"};
961 if ($getterStringUsesImp && $reflect && !$url && $codeGenerator->InheritsInterface($interface, "Node") && $codeGenerator->IsStringType($attrType)) {
962 # Generate super-compact call for regular attribute getter:
963 my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
964 push(@implContentInternals, " Element* imp = V8Element::toNative(info.Holder());\n");
965 push(@implContentInternals, " return v8String(imp->${functionName}(" . join(", ", @arguments) . "), info.GetIsolate(), ReturnUnsafeHandle);\n");
966 push(@implContentInternals, "}\n\n");
967 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
969 # Skip the rest of the function!
971 if ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
972 push(@implContentInternals, <<END);
973 v8::Handle<v8::String> propertyName = v8::String::NewSymbol("${attrName}");
974 v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(propertyName);
975 if (!value.IsEmpty())
979 if (!$attribute->isStatic) {
980 push(@implContentInternals, <<END);
981 ${interfaceName}* imp = ${v8InterfaceName}::toNative(info.Holder());
986 # Generate security checks if necessary
987 if ($attribute->signature->extendedAttributes->{"CheckSecurityForNode"}) {
988 push(@implContentInternals, " if (!BindingSecurity::shouldAllowAccessToNode(BindingState::instance(), imp->" . $attribute->signature->name . "()))\n return v8::Handle<v8::Value>(v8Null(info.GetIsolate()));\n\n");
991 my $useExceptions = 1 if @{$attribute->getterExceptions};
992 if ($useExceptions) {
993 AddToImplIncludes("ExceptionCode.h");
994 push(@implContentInternals, " ExceptionCode ec = 0;\n");
997 my $returnType = $attribute->signature->type;
1000 if ($getterStringUsesImp) {
1001 my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute);
1002 push(@arguments, "ec") if $useExceptions;
1003 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
1004 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
1005 AddToImplIncludes("${implementedBy}.h");
1006 unshift(@arguments, "imp") if !$attribute->isStatic;
1007 $functionName = "${implementedBy}::${functionName}";
1008 } elsif ($attribute->isStatic) {
1009 $functionName = "${interfaceName}::${functionName}";
1011 $functionName = "imp->${functionName}";
1013 unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentInternals, " ", 0));
1014 $getterString = "${functionName}(" . join(", ", @arguments) . ")";
1016 $getterString = "impInstance";
1020 if ($attribute->signature->type eq "EventListener" && $interface->name eq "DOMWindow") {
1021 push(@implContentInternals, " if (!imp->document())\n");
1022 push(@implContentInternals, " return v8Undefined();\n");
1025 if ($useExceptions) {
1026 if ($nativeType =~ /^V8StringResource/) {
1027 push(@implContentInternals, " " . ConvertToV8StringResource($attribute->signature, $nativeType, "v", $getterString) . ";\n");
1029 push(@implContentInternals, " $nativeType v = $getterString;\n");
1031 push(@implContentInternals, " if (UNLIKELY(ec))\n");
1032 push(@implContentInternals, " return setDOMException(ec, info.GetIsolate());\n");
1034 if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
1035 push(@implContentInternals, " if (state.hadException())\n");
1036 push(@implContentInternals, " return throwError(state.exception(), info.GetIsolate());\n");
1040 $result .= ".release()" if ($codeGenerator->IsRefPtrType($returnType));
1042 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
1043 $result = $getterString;
1044 # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
1045 $result = "static_pointer_cast<SVGAnimatedEnumeration>($result)" if $returnType eq "SVGAnimatedEnumeration";
1048 # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get
1049 # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to
1050 # the newly created wrapper into an internal field of the holder object.
1051 if ((!$codeGenerator->InheritsInterface($interface, "Node") && $attrName ne "self" && IsWrapperType($returnType) && (IsReadonly($attribute) || $attribute->signature->extendedAttributes->{"Replaceable"} || $attrName eq "location")
1052 && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow"
1053 && $returnType ne "MessagePortArray"
1054 && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))
1055 || $attribute->signature->extendedAttributes->{"V8CacheAttributeForGC"}) {
1057 my $arrayType = $codeGenerator->GetArrayType($returnType);
1059 if (!$codeGenerator->SkipIncludeHeader($arrayType)) {
1060 AddToImplIncludes("V8$arrayType.h");
1061 AddToImplIncludes("$arrayType.h");
1063 push(@implContentInternals, " return v8Array(${getterString}, info.GetIsolate());\n");
1064 push(@implContentInternals, "}\n\n");
1068 AddIncludesForType($returnType);
1069 # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
1070 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
1071 push(@implContentInternals, " RefPtr<$returnType> result = ${getterString};\n");
1072 push(@implContentInternals, " v8::Handle<v8::Value> wrapper = result.get() ? v8::Handle<v8::Value>(DOMDataStore::getWrapper(result.get(), info.GetIsolate())) : v8Undefined();\n");
1073 push(@implContentInternals, " if (wrapper.IsEmpty()) {\n");
1074 push(@implContentInternals, " wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());\n"); # FIXME: Could use wrap here since the wrapper is empty.
1075 push(@implContentInternals, " if (!wrapper.IsEmpty())\n");
1076 push(@implContentInternals, " V8HiddenPropertyName::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n");
1077 push(@implContentInternals, " }\n");
1078 push(@implContentInternals, " return wrapper;\n");
1079 push(@implContentInternals, "}\n\n");
1080 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1084 if (($codeGenerator->IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") and $codeGenerator->IsSVGTypeNeedingTearOff($attrType)) {
1085 AddToImplIncludes("V8$attrType.h");
1086 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
1087 # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
1088 push(@implContentInternals, " return toV8Fast(static_cast<$svgNativeType*>($result), info, imp);\n");
1089 } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$/) {
1090 AddToImplIncludes("V8$attrType.h");
1091 AddToImplIncludes("SVGPropertyTearOff.h");
1092 my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($attrType);
1094 if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
1095 my $getter = $result;
1096 $getter =~ s/imp->//;
1097 $getter =~ s/\(\)//;
1099 my $updateMethod = "&${interfaceName}::update" . $codeGenerator->WK_ucfirst($getter);
1101 my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName);
1102 if ($selfIsTearOffType) {
1103 AddToImplIncludes("SVGStaticPropertyWithParentTearOff.h");
1104 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyWithParentTearOff<$interfaceName, /;
1106 if ($result =~ /matrix/ and $interfaceName eq "SVGTransform") {
1107 # SVGTransform offers a matrix() method for internal usage that returns an AffineTransform
1108 # and a svgMatrix() method returning a SVGMatrix, used for the bindings.
1109 $result =~ s/matrix/svgMatrix/;
1112 $wrappedValue = "WTF::getPtr(${tearOffType}::create(wrapper, $result, $updateMethod))";
1114 AddToImplIncludes("SVGStaticPropertyTearOff.h");
1115 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$interfaceName, /;
1117 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $result, $updateMethod))";
1119 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
1120 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $result))";
1121 } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
1122 $wrappedValue = "WTF::getPtr($result)";
1124 $wrappedValue = "WTF::getPtr(${tearOffType}::create($result))";
1126 push(@implContentInternals, " return toV8Fast($wrappedValue, info, imp);\n");
1127 } elsif ($attribute->signature->type eq "MessagePortArray") {
1128 AddToImplIncludes("MessagePort.h");
1129 AddToImplIncludes("V8MessagePort.h");
1130 my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
1131 push(@implContentInternals, <<END);
1132 MessagePortArray* ports = imp->${getterFunc}();
1134 return v8::Array::New(0);
1135 MessagePortArray portsCopy(*ports);
1136 v8::Local<v8::Array> portArray = v8::Array::New(portsCopy.size());
1137 for (size_t i = 0; i < portsCopy.size(); ++i)
1138 portArray->Set(v8Integer(i, info.GetIsolate()), toV8Fast(portsCopy[i].get(), info, imp));
1141 } elsif ($attribute->signature->type eq "SerializedScriptValue" && $attrExt->{"CachedAttribute"}) {
1142 my $getterFunc = $codeGenerator->WK_lcfirst($attribute->signature->name);
1143 push(@implContentInternals, <<END);
1144 RefPtr<SerializedScriptValue> serialized = imp->${getterFunc}();
1145 value = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8Null(info.GetIsolate()));
1146 info.Holder()->SetHiddenValue(propertyName, value);
1150 push(@implContentInternals, " return " . NativeToJSValue($attribute->signature, $result, "info.Holder()", "info.GetIsolate()", "info", "imp", "ReturnUnsafeHandle").";\n");
1153 push(@implContentInternals, "}\n\n"); # end of getter
1154 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1157 sub GenerateReplaceableAttrSetterCallback
1159 my $interface = shift;
1160 my $interfaceName = $interface->name;
1162 push(@implContentInternals, "static void ${interfaceName}ReplaceableAttrSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n");
1163 push(@implContentInternals, "{\n");
1164 push(@implContentInternals, GenerateFeatureObservation($interface->extendedAttributes->{"V8MeasureAs"}));
1165 push(@implContentInternals, " return ${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetter(name, value, info);\n");
1166 push(@implContentInternals, "}\n\n");
1169 sub GenerateReplaceableAttrSetter
1171 my $interface = shift;
1172 my $interfaceName = $interface->name;
1174 push(@implContentInternals, <<END);
1175 static void ${interfaceName}ReplaceableAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
1178 if ($interface->extendedAttributes->{"CheckSecurity"}) {
1179 AddToImplIncludes("Frame.h");
1180 push(@implContentInternals, <<END);
1181 ${interfaceName}* imp = V8${interfaceName}::toNative(info.Holder());
1182 if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
1187 push(@implContentInternals, <<END);
1188 info.This()->ForceSet(name, value);
1194 sub GenerateNormalAttrSetterCallback
1196 my $attribute = shift;
1197 my $interface = shift;
1199 my $interfaceName = $interface->name;
1200 my $v8InterfaceName = "V8$interfaceName";
1201 my $attrExt = $attribute->signature->extendedAttributes;
1202 my $attrName = $attribute->signature->name;
1204 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1205 push(@implContentInternals, "#if ${conditionalString}\n\n") if $conditionalString;
1207 push(@implContentInternals, "static void ${attrName}AttrSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n");
1208 push(@implContentInternals, "{\n");
1209 push(@implContentInternals, GenerateFeatureObservation($attrExt->{"V8MeasureAs"}));
1210 if (HasCustomSetter($attrExt)) {
1211 push(@implContentInternals, " ${v8InterfaceName}::${attrName}AttrSetterCustom(name, value, info);\n");
1213 push(@implContentInternals, " ${interfaceName}V8Internal::${attrName}AttrSetter(name, value, info);\n");
1215 push(@implContentInternals, "}\n\n");
1216 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1219 sub GenerateNormalAttrSetter
1221 my $attribute = shift;
1222 my $interface = shift;
1224 my $interfaceName = $interface->name;
1225 my $v8InterfaceName = "V8$interfaceName";
1226 my $attrName = $attribute->signature->name;
1227 my $attrExt = $attribute->signature->extendedAttributes;
1228 my $attrType = $attribute->signature->type;
1230 if (HasCustomSetter($attrExt)) {
1234 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
1235 push(@implContentInternals, "#if ${conditionalString}\n\n") if $conditionalString;
1236 push(@implContentInternals, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n");
1237 push(@implContentInternals, "{\n");
1239 # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an
1240 # interface type, then if the incoming value does not implement that interface, a TypeError is
1241 # thrown rather than silently passing NULL to the C++ code.
1242 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
1243 # strings and numbers, so do not throw TypeError if the attribute is of these types.
1244 if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) {
1245 my $argType = $attribute->signature->type;
1246 if (IsWrapperType($argType)) {
1247 push(@implContentInternals, " if (!isUndefinedOrNull(value) && !V8${argType}::HasInstance(value, info.GetIsolate())) {\n");
1248 push(@implContentInternals, " throwTypeError(0, info.GetIsolate());\n");
1249 push(@implContentInternals, " return;\n");
1250 push(@implContentInternals, " }\n");
1254 my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName);
1255 if ($svgNativeType) {
1256 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
1257 if ($svgWrappedNativeType =~ /List$/) {
1258 push(@implContentInternals, <<END);
1259 $svgNativeType* imp = ${v8InterfaceName}::toNative(info.Holder());
1262 AddToImplIncludes("ExceptionCode.h");
1263 push(@implContentInternals, " $svgNativeType* wrapper = ${v8InterfaceName}::toNative(info.Holder());\n");
1264 push(@implContentInternals, " if (wrapper->isReadOnly()) {\n");
1265 push(@implContentInternals, " setDOMException(NO_MODIFICATION_ALLOWED_ERR, info.GetIsolate());\n");
1266 push(@implContentInternals, " return;\n");
1267 push(@implContentInternals, " }\n");
1268 push(@implContentInternals, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1269 push(@implContentInternals, " $svgWrappedNativeType* imp = &impInstance;\n");
1271 } elsif ($attrExt->{"V8OnProto"}) {
1272 push(@implContentInternals, <<END);
1273 ${interfaceName}* imp = ${v8InterfaceName}::toNative(info.Holder());
1276 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
1277 if ($reflect && $codeGenerator->InheritsInterface($interface, "Node") && $codeGenerator->IsStringType($attrType)) {
1278 # Generate super-compact call for regular attribute setter:
1279 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
1280 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
1281 AddToImplIncludes("${namespace}.h");
1282 push(@implContentInternals, " Element* imp = V8Element::toNative(info.Holder());\n");
1283 push(@implContentInternals, " V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, stringResource, value);\n");
1284 push(@implContentInternals, " imp->setAttribute(${namespace}::${contentAttributeName}Attr, stringResource);\n");
1285 push(@implContentInternals, "}\n\n");
1286 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1288 # Skip the rest of the function!
1291 if (!$attribute->isStatic) {
1292 push(@implContentInternals, <<END);
1293 ${interfaceName}* imp = ${v8InterfaceName}::toNative(info.Holder());
1298 my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
1299 if ($attribute->signature->type eq "EventListener") {
1300 if ($interface->name eq "DOMWindow") {
1301 push(@implContentInternals, " if (!imp->document())\n");
1302 push(@implContentInternals, " return;\n");
1305 my $value = JSValueToNative($attribute->signature, "value", "info.GetIsolate()");
1306 my $arrayType = $codeGenerator->GetArrayType($nativeType);
1308 if ($nativeType =~ /^V8StringResource/) {
1309 push(@implContentInternals, " " . ConvertToV8StringResource($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
1310 } elsif ($arrayType) {
1311 push(@implContentInternals, " Vector<$arrayType> v = $value;\n");
1313 push(@implContentInternals, " $nativeType v = $value;\n");
1317 if ($codeGenerator->IsEnumType($attrType)) {
1318 # setter ignores invalid enumeration values
1319 my @enumValues = $codeGenerator->ValidEnumValues($attrType);
1320 my @validEqualities = ();
1321 foreach my $enumValue (@enumValues) {
1322 push(@validEqualities, "string == \"$enumValue\"");
1324 my $enumValidationExpression = join(" || ", @validEqualities);
1325 push(@implContentInternals, <<END);
1327 if (!($enumValidationExpression))
1333 my $returnType = $attribute->signature->type;
1334 if ($codeGenerator->IsRefPtrType($returnType) && !$codeGenerator->GetArrayType($returnType)) {
1335 $result = "WTF::getPtr(" . $result . ")";
1338 my $useExceptions = 1 if @{$attribute->setterExceptions};
1340 if ($useExceptions) {
1341 AddToImplIncludes("ExceptionCode.h");
1342 push(@implContentInternals, " ExceptionCode ec = 0;\n");
1345 if ($interfaceName eq "SVGNumber") {
1346 push(@implContentInternals, " *imp = $result;\n");
1348 if ($attribute->signature->type eq "EventListener") {
1349 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
1350 AddToImplIncludes("V8AbstractEventListener.h");
1351 if (!$codeGenerator->InheritsInterface($interface, "Node")) {
1352 push(@implContentInternals, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, ${v8InterfaceName}::eventListenerCacheIndex, info.GetIsolate());\n");
1354 AddToImplIncludes("V8EventListenerList.h");
1355 if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") {
1356 AddToImplIncludes("V8WorkerContextErrorHandler.h");
1357 push(@implContentInternals, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)");
1358 } elsif ($interfaceName eq "DOMWindow" and $attribute->signature->name eq "onerror") {
1359 AddToImplIncludes("V8WindowErrorHandler.h");
1360 push(@implContentInternals, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WindowErrorHandler>(value, true)");
1362 push(@implContentInternals, " imp->set$implSetterFunctionName(V8EventListenerList::getEventListener(value, true, ListenerFindOrCreate)");
1364 push(@implContentInternals, ", ec") if $useExceptions;
1365 push(@implContentInternals, ");\n");
1367 my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute);
1368 push(@arguments, $result);
1369 push(@arguments, "ec") if $useExceptions;
1370 if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) {
1371 my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"};
1372 AddToImplIncludes("${implementedBy}.h");
1373 unshift(@arguments, "imp") if !$attribute->isStatic;
1374 $functionName = "${implementedBy}::${functionName}";
1375 } elsif ($attribute->isStatic) {
1376 $functionName = "${interfaceName}::${functionName}";
1378 $functionName = "imp->${functionName}";
1380 unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContentInternals, " ", 1));
1381 push(@implContentInternals, " ${functionName}(" . join(", ", @arguments) . ");\n");
1385 if ($useExceptions) {
1386 push(@implContentInternals, " if (UNLIKELY(ec))\n");
1387 push(@implContentInternals, " setDOMException(ec, info.GetIsolate());\n");
1390 if ($codeGenerator->ExtendedAttributeContains($attribute->signature->extendedAttributes->{"CallWith"}, "ScriptState")) {
1391 push(@implContentInternals, " if (state.hadException())\n");
1392 push(@implContentInternals, " throwError(state.exception(), info.GetIsolate());\n");
1395 if ($svgNativeType) {
1396 if ($useExceptions) {
1397 push(@implContentInternals, " if (!ec)\n");
1398 push(@implContentInternals, " wrapper->commitChange();\n");
1400 push(@implContentInternals, " wrapper->commitChange();\n");
1404 if ($attribute->signature->type eq "SerializedScriptValue" && $attribute->signature->extendedAttributes->{"CachedAttribute"}) {
1405 push(@implContentInternals, <<END);
1406 info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // Invalidate the cached value.
1410 push(@implContentInternals, " return;\n");
1411 push(@implContentInternals, "}\n\n"); # end of setter
1412 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1415 sub GenerateParametersCheckExpression
1417 my $numParameters = shift;
1418 my $function = shift;
1420 my @andExpression = ();
1421 push(@andExpression, "args.Length() == $numParameters");
1422 my $parameterIndex = 0;
1423 foreach my $parameter (@{$function->parameters}) {
1424 last if $parameterIndex >= $numParameters;
1425 my $value = "args[$parameterIndex]";
1426 my $type = $parameter->type;
1428 # Only DOMString or wrapper types are checked.
1429 # For DOMString with StrictTypeChecking only Null, Undefined and Object
1430 # are accepted for compatibility. Otherwise, no restrictions are made to
1431 # match the non-overloaded behavior.
1432 # FIXME: Implement WebIDL overload resolution algorithm.
1433 if ($codeGenerator->IsStringType($type)) {
1434 if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
1435 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())");
1437 } elsif ($parameter->extendedAttributes->{"Callback"}) {
1438 # For Callbacks only checks if the value is null or object.
1439 push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction())");
1440 } elsif ($codeGenerator->GetArrayType($type) || $codeGenerator->GetSequenceType($type)) {
1441 if ($parameter->isNullable) {
1442 push(@andExpression, "(${value}->IsNull() || ${value}->IsArray())");
1444 push(@andExpression, "(${value}->IsArray())");
1446 } elsif (IsWrapperType($type)) {
1447 if ($parameter->isNullable) {
1448 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value, args.GetIsolate()))");
1450 push(@andExpression, "(V8${type}::HasInstance($value, args.GetIsolate()))");
1456 my $res = join(" && ", @andExpression);
1457 $res = "($res)" if @andExpression > 1;
1461 sub GenerateFunctionParametersCheck
1463 my $function = shift;
1465 my @orExpression = ();
1466 my $numParameters = 0;
1467 my $hasVariadic = 0;
1468 my $numMandatoryParams = @{$function->parameters};
1469 foreach my $parameter (@{$function->parameters}) {
1470 if ($parameter->extendedAttributes->{"Optional"}) {
1471 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1472 $numMandatoryParams--;
1474 if ($parameter->isVariadic) {
1480 if (!$hasVariadic) {
1481 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
1483 return ($numMandatoryParams, join(" || ", @orExpression));
1486 sub GenerateOverloadedFunction
1488 my $function = shift;
1489 my $interface = shift;
1490 my $interfaceName = $interface->name;
1492 # Generate code for choosing the correct overload to call. Overloads are
1493 # chosen based on the total number of arguments passed and the type of
1494 # values passed in non-primitive argument slots. When more than a single
1495 # overload is applicable, precedence is given according to the order of
1496 # declaration in the IDL.
1498 my $name = $function->signature->name;
1499 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1500 my $leastNumMandatoryParams = 255;
1501 push(@implContentInternals, "#if ${conditionalString}\n\n") if $conditionalString;
1502 push(@implContentInternals, <<END);
1503 static v8::Handle<v8::Value> ${name}Method(const v8::Arguments& args)
1506 push(@implContentInternals, GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"}));
1508 foreach my $overload (@{$function->{overloads}}) {
1509 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($overload);
1510 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
1511 push(@implContentInternals, " if ($parametersCheck)\n");
1512 my $overloadedIndexString = $overload->{overloadIndex};
1513 push(@implContentInternals, " return ${name}${overloadedIndexString}Method(args);\n");
1515 if ($leastNumMandatoryParams >= 1) {
1516 push(@implContentInternals, " if (args.Length() < $leastNumMandatoryParams)\n");
1517 push(@implContentInternals, " return throwNotEnoughArgumentsError(args.GetIsolate());\n");
1519 push(@implContentInternals, <<END);
1520 return throwTypeError(0, args.GetIsolate());
1522 push(@implContentInternals, "}\n\n");
1523 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1526 sub GenerateFunctionCallback
1528 my $function = shift;
1529 my $interface = shift;
1531 my $interfaceName = $interface->name;
1532 my $v8InterfaceName = "V8$interfaceName";
1533 my $name = $function->signature->name;
1535 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1536 push(@implContentInternals, "#if ${conditionalString}\n\n") if $conditionalString;
1537 push(@implContentInternals, <<END);
1538 static v8::Handle<v8::Value> ${name}MethodCallback(const v8::Arguments& args)
1541 push(@implContentInternals, GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"}));
1542 if (HasCustomMethod($function->signature->extendedAttributes)) {
1543 push(@implContentInternals, " return ${v8InterfaceName}::${name}MethodCustom(args);\n");
1545 push(@implContentInternals, " return ${interfaceName}V8Internal::${name}Method(args);\n");
1547 push(@implContentInternals, "}\n\n");
1548 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1551 sub GenerateFunction
1553 my $function = shift;
1554 my $interface = shift;
1556 my $interfaceName = $interface->name;
1557 my $v8InterfaceName = "V8$interfaceName";
1558 my $name = $function->signature->name;
1559 my $funcExt = $function->signature->extendedAttributes;
1561 if (HasCustomMethod($funcExt)) {
1565 if (@{$function->{overloads}} > 1) {
1566 # Append a number to an overloaded method's name to make it unique:
1567 $name = $name . $function->{overloadIndex};
1570 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
1571 push(@implContentInternals, "#if ${conditionalString}\n\n") if $conditionalString;
1572 push(@implContentInternals, "static v8::Handle<v8::Value> ${name}Method(const v8::Arguments& args)\n");
1573 push(@implContentInternals, "{\n");
1575 if ($name eq "addEventListener" || $name eq "removeEventListener") {
1576 my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only";
1577 my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()";
1578 my $hiddenDependencyAction = ($name eq "addEventListener") ? "create" : "remove";
1580 AddToImplIncludes("V8EventListenerList.h");
1581 push(@implContentInternals, <<END);
1582 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[1], false, ListenerFind${lookupType});
1584 V8TRYCATCH_FOR_V8STRINGRESOURCE(V8StringResource<WithNullCheck>, stringResource, args[0]);
1585 V8${interfaceName}::toNative(args.Holder())->${name}(stringResource, listener${passRefPtrHandling}, args[2]->BooleanValue());
1587 if (!$codeGenerator->InheritsInterface($interface, "Node")) {
1588 push(@implContentInternals, <<END);
1589 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${interfaceName}::eventListenerCacheIndex, args.GetIsolate());
1592 push(@implContentInternals, <<END);
1594 return v8Undefined();
1598 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1602 push(@implContentInternals, GenerateArgumentsCountCheck($function, $interface));
1604 if ($name eq "set" and $interface->extendedAttributes->{"TypedArray"}) {
1605 AddToImplIncludes("V8ArrayBufferViewCustom.h");
1606 push(@implContentInternals, <<END);
1607 return setWebGLArrayHelper<$interfaceName, ${v8InterfaceName}>(args);
1614 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
1616 if ($svgNativeType) {
1617 my $nativeClassName = GetNativeType($interfaceName);
1618 if ($interfaceName =~ /List$/) {
1619 push(@implContentInternals, " $nativeClassName imp = ${v8InterfaceName}::toNative(args.Holder());\n");
1621 AddToImplIncludes("ExceptionCode.h");
1622 push(@implContentInternals, " $nativeClassName wrapper = ${v8InterfaceName}::toNative(args.Holder());\n");
1623 push(@implContentInternals, " if (wrapper->isReadOnly())\n");
1624 push(@implContentInternals, " return setDOMException(NO_MODIFICATION_ALLOWED_ERR, args.GetIsolate());\n");
1625 my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($interfaceName);
1626 push(@implContentInternals, " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n");
1627 push(@implContentInternals, " $svgWrappedNativeType* imp = &impInstance;\n");
1629 } elsif (!$function->isStatic) {
1630 push(@implContentInternals, <<END);
1631 ${interfaceName}* imp = ${v8InterfaceName}::toNative(args.Holder());
1635 # Check domain security if needed
1636 if ($interface->extendedAttributes->{"CheckSecurity"} && !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
1637 # We have not find real use cases yet.
1638 AddToImplIncludes("Frame.h");
1639 push(@implContentInternals, <<END);
1640 if (!BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame()))
1641 return v8Undefined();
1645 my $raisesExceptions = @{$function->raisesExceptions};
1646 if (!$raisesExceptions) {
1647 foreach my $parameter (@{$function->parameters}) {
1648 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1649 $raisesExceptions = 1;
1654 if ($raisesExceptions) {
1655 AddToImplIncludes("ExceptionCode.h");
1656 push(@implContentInternals, " ExceptionCode ec = 0;\n");
1657 push(@implContentInternals, " {\n");
1658 # The brace here is needed to prevent the ensuing 'goto fail's from jumping past constructors
1659 # of objects (like Strings) declared later, causing compile errors. The block scope ends
1660 # right before the label 'fail:'.
1663 if ($function->signature->extendedAttributes->{"CheckSecurityForNode"}) {
1664 push(@implContentInternals, " if (!BindingSecurity::shouldAllowAccessToNode(BindingState::instance(), imp->" . $function->signature->name . "(ec)))\n");
1665 push(@implContentInternals, " return v8::Handle<v8::Value>(v8Null(args.GetIsolate()));\n");
1669 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
1670 push(@implContentInternals, $parameterCheckString);
1672 # Build the function call string.
1673 push(@implContentInternals, GenerateFunctionCallString($function, $paramIndex, " ", $interfaceName, %replacements));
1675 if ($raisesExceptions) {
1676 push(@implContentInternals, " }\n");
1677 push(@implContentInternals, " fail:\n");
1678 push(@implContentInternals, " return setDOMException(ec, args.GetIsolate());\n");
1681 push(@implContentInternals, "}\n\n");
1682 push(@implContentInternals, "#endif // ${conditionalString}\n\n") if $conditionalString;
1685 sub GenerateCallWith
1687 my $callWith = shift;
1688 return () unless $callWith;
1689 my $outputArray = shift;
1691 my $returnVoid = shift;
1692 my $function = shift;
1695 if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) {
1696 push(@$outputArray, $indent . "ScriptState* currentState = ScriptState::current();\n");
1697 push(@$outputArray, $indent . "if (!currentState)\n");
1698 push(@$outputArray, $indent . " return" . ($returnVoid ? "" : " v8Undefined()") . ";\n");
1699 push(@$outputArray, $indent . "ScriptState& state = *currentState;\n");
1700 push(@callWithArgs, "&state");
1702 if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptExecutionContext")) {
1703 push(@$outputArray, $indent . "ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n");
1704 push(@callWithArgs, "scriptContext");
1706 if ($function and $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments")) {
1707 push(@$outputArray, $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(args, " . @{$function->parameters} . "));\n");
1708 push(@callWithArgs, "scriptArguments.release()");
1709 AddToImplIncludes("ScriptArguments.h");
1710 AddToImplIncludes("ScriptCallStackFactory.h");
1712 return @callWithArgs;
1715 sub GenerateArgumentsCountCheck
1717 my $function = shift;
1718 my $interface = shift;
1720 my $numMandatoryParams = 0;
1721 my $allowNonOptional = 1;
1722 foreach my $param (@{$function->parameters}) {
1723 if ($param->extendedAttributes->{"Optional"} or $param->isVariadic) {
1724 $allowNonOptional = 0;
1726 die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if !$allowNonOptional;
1727 $numMandatoryParams++;
1731 my $argumentsCountCheckString = "";
1732 if ($numMandatoryParams >= 1) {
1733 $argumentsCountCheckString .= " if (args.Length() < $numMandatoryParams)\n";
1734 $argumentsCountCheckString .= " return throwNotEnoughArgumentsError(args.GetIsolate());\n";
1736 return $argumentsCountCheckString;
1741 my $paramName = shift;
1744 foreach my $param (@paramList) {
1745 if ($paramName eq $param) {
1753 sub GenerateParametersCheck
1755 my $function = shift;
1756 my $interfaceName = shift;
1758 my $parameterCheckString = "";
1760 my @paramTransferListNames = ();
1761 my %replacements = ();
1763 foreach my $parameter (@{$function->parameters}) {
1764 my $nativeType = GetNativeTypeFromSignature($parameter, $paramIndex);
1766 # Optional arguments with [Optional] should generate an early call with fewer arguments.
1767 # Optional arguments with [Optional=...] should not generate the early call.
1768 # Optional Dictionary arguments always considered to have default of empty dictionary.
1769 my $optional = $parameter->extendedAttributes->{"Optional"};
1770 if ($optional && $optional ne "DefaultIsUndefined" && $optional ne "DefaultIsNullString" && $nativeType ne "Dictionary" && !$parameter->extendedAttributes->{"Callback"}) {
1771 $parameterCheckString .= " if (args.Length() <= $paramIndex) {\n";
1772 my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $interfaceName, %replacements);
1773 $parameterCheckString .= $functionCall;
1774 $parameterCheckString .= " }\n";
1777 my $parameterDefaultPolicy = "DefaultIsUndefined";
1778 if ($optional and $optional eq "DefaultIsNullString") {
1779 $parameterDefaultPolicy = "DefaultIsNullString";
1782 my $parameterName = $parameter->name;
1783 if (GetIndexOf($parameterName, @paramTransferListNames) != -1) {
1784 $replacements{$parameterName} = "messagePortArray" . ucfirst($parameterName);
1789 AddToImplIncludes("ExceptionCode.h");
1790 if ($parameter->extendedAttributes->{"Callback"}) {
1791 my $v8InterfaceName = "V8" . $parameter->type;
1792 AddToImplIncludes("$v8InterfaceName.h");
1794 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $parameterName;\n";
1795 $parameterCheckString .= " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n";
1796 $parameterCheckString .= " if (!args[$paramIndex]->IsFunction())\n";
1797 $parameterCheckString .= " return throwTypeError(0, args.GetIsolate());\n";
1798 $parameterCheckString .= " $parameterName = ${v8InterfaceName}::create(args[$paramIndex], getScriptExecutionContext());\n";
1799 $parameterCheckString .= " }\n";
1801 $parameterCheckString .= " if (args.Length() <= $paramIndex || !args[$paramIndex]->IsFunction())\n";
1802 $parameterCheckString .= " return throwTypeError(0, args.GetIsolate());\n";
1803 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $parameterName = ${v8InterfaceName}::create(args[$paramIndex], getScriptExecutionContext());\n";
1805 } elsif ($parameter->extendedAttributes->{"Clamp"}) {
1806 my $nativeValue = "${parameterName}NativeValue";
1807 my $paramType = $parameter->type;
1808 $parameterCheckString .= " $paramType $parameterName = 0;\n";
1809 $parameterCheckString .= " V8TRYCATCH(double, $nativeValue, args[$paramIndex]->NumberValue());\n";
1810 $parameterCheckString .= " if (!std::isnan($nativeValue))\n";
1811 $parameterCheckString .= " $parameterName = clampTo<$paramType>($nativeValue);\n";
1812 } elsif ($parameter->type eq "SerializedScriptValue") {
1813 AddToImplIncludes("SerializedScriptValue.h");
1814 my $useTransferList = 0;
1815 my $transferListName = "";
1816 my $TransferListName = "";
1817 if ($parameter->extendedAttributes->{"TransferList"}) {
1818 $transferListName = $parameter->extendedAttributes->{"TransferList"};
1819 push(@paramTransferListNames, $transferListName);
1821 my @allParameterNames = ();
1822 foreach my $parameter (@{$function->parameters}) {
1823 push(@allParameterNames, $parameter->name);
1825 my $transferListIndex = GetIndexOf($transferListName, @allParameterNames);
1826 if ($transferListIndex == -1) {
1827 die "IDL error: TransferList refers to a nonexistent argument";
1830 AddToImplIncludes("wtf/ArrayBuffer.h");
1831 AddToImplIncludes("MessagePort.h");
1832 $TransferListName = ucfirst($transferListName);
1833 $parameterCheckString .= " MessagePortArray messagePortArray$TransferListName;\n";
1834 $parameterCheckString .= " ArrayBufferArray arrayBufferArray$TransferListName;\n";
1835 $parameterCheckString .= " if (args.Length() > $transferListIndex) {\n";
1836 $parameterCheckString .= " if (!extractTransferables(args[$transferListIndex], messagePortArray$TransferListName, arrayBufferArray$TransferListName, args.GetIsolate()))\n";
1837 $parameterCheckString .= " return throwTypeError(\"Could not extract transferables\", args.GetIsolate());\n";
1838 $parameterCheckString .= " }\n";
1839 $useTransferList = 1;
1841 $parameterCheckString .= " bool ${parameterName}DidThrow = false;\n";
1842 if (!$useTransferList) {
1843 $parameterCheckString .= " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow, args.GetIsolate());\n";
1845 $parameterCheckString .= " $nativeType $parameterName = SerializedScriptValue::create(args[$paramIndex], &messagePortArray$TransferListName, &arrayBufferArray$TransferListName, ${parameterName}DidThrow, args.GetIsolate());\n";
1847 $parameterCheckString .= " if (${parameterName}DidThrow)\n";
1848 $parameterCheckString .= " return v8Undefined();\n";
1849 } elsif (TypeCanFailConversion($parameter)) {
1850 $parameterCheckString .= " $nativeType $parameterName = " .
1851 JSValueToNative($parameter, "args[$paramIndex]", "args.GetIsolate()") . ";\n";
1852 $parameterCheckString .= " if (UNLIKELY(!$parameterName)) {\n";
1853 $parameterCheckString .= " ec = TYPE_MISMATCH_ERR;\n";
1854 $parameterCheckString .= " goto fail;\n";
1855 $parameterCheckString .= " }\n";
1856 } elsif ($parameter->isVariadic) {
1857 my $nativeElementType = GetNativeType($parameter->type);
1858 if ($nativeElementType =~ />$/) {
1859 $nativeElementType .= " ";
1862 my $argType = $parameter->type;
1863 if (IsWrapperType($argType)) {
1864 $parameterCheckString .= " Vector<$nativeElementType> $parameterName;\n";
1865 $parameterCheckString .= " for (int i = $paramIndex; i < args.Length(); ++i) {\n";
1866 $parameterCheckString .= " if (!V8${argType}::HasInstance(args[i], args.GetIsolate()))\n";
1867 $parameterCheckString .= " return throwTypeError(0, args.GetIsolate());\n";
1868 $parameterCheckString .= " $parameterName.append(V8${argType}::toNative(v8::Handle<v8::Object>::Cast(args[i])));\n";
1869 $parameterCheckString .= " }\n";
1871 $parameterCheckString .= " V8TRYCATCH(Vector<$nativeElementType>, $parameterName, toNativeArguments<$nativeElementType>(args, $paramIndex));\n";
1873 } elsif ($nativeType =~ /^V8StringResource/) {
1874 my $value = JSValueToNative($parameter, $optional && $optional eq "DefaultIsNullString" ? "argumentOrNull(args, $paramIndex)" : "args[$paramIndex]", "args.GetIsolate()");
1875 $parameterCheckString .= " " . ConvertToV8StringResource($parameter, $nativeType, $parameterName, $value) . "\n";
1877 # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
1878 # interface type, then if the incoming value does not implement that interface, a TypeError
1879 # is thrown rather than silently passing NULL to the C++ code.
1880 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
1881 # to both strings and numbers, so do not throw TypeError if the argument is of these
1883 if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
1884 my $argValue = "args[$paramIndex]";
1885 my $argType = $parameter->type;
1886 if (IsWrapperType($argType)) {
1887 $parameterCheckString .= " if (args.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue, args.GetIsolate()))\n";
1888 $parameterCheckString .= " return throwTypeError(0, args.GetIsolate());\n";
1891 $parameterCheckString .= " V8TRYCATCH($nativeType, $parameterName, " .
1892 JSValueToNative($parameter, $optional && $optional eq "DefaultIsNullString" ? "argumentOrNull(args, $paramIndex)" : "args[$paramIndex]", "args.GetIsolate()") . ");\n";
1893 if ($nativeType eq 'Dictionary') {
1894 $parameterCheckString .= " if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject())\n";
1895 $parameterCheckString .= " return throwTypeError(\"Not an object.\", args.GetIsolate());\n";
1899 if ($parameter->extendedAttributes->{"IsIndex"}) {
1900 $parameterCheckString .= " if (UNLIKELY($parameterName < 0)) {\n";
1901 $parameterCheckString .= " ec = INDEX_SIZE_ERR;\n";
1902 $parameterCheckString .= " goto fail;\n";
1903 $parameterCheckString .= " }\n";
1908 return ($parameterCheckString, $paramIndex, %replacements);
1911 sub GenerateOverloadedConstructorCallback
1913 my $interface = shift;
1914 my $interfaceName = $interface->name;
1916 push(@implContentInternals, <<END);
1917 static v8::Handle<v8::Value> constructor(const v8::Arguments& args)
1920 my $leastNumMandatoryParams = 255;
1921 foreach my $constructor (@{$interface->constructors}) {
1922 my $name = "constructor" . $constructor->{overloadedIndex};
1923 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($constructor);
1924 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
1925 push(@implContentInternals, " if ($parametersCheck)\n");
1926 push(@implContentInternals, " return ${interfaceName}V8Internal::${name}(args);\n");
1928 if ($leastNumMandatoryParams >= 1) {
1929 push(@implContentInternals, " if (args.Length() < $leastNumMandatoryParams)\n");
1930 push(@implContentInternals, " return throwNotEnoughArgumentsError(args.GetIsolate());\n");
1932 push(@implContentInternals, <<END);
1933 return throwTypeError(0, args.GetIsolate());
1935 push(@implContentInternals, "}\n\n");
1938 sub GenerateSingleConstructorCallback
1940 my $interface = shift;
1941 my $function = shift;
1943 my $interfaceName = $interface->name;
1944 my $overloadedIndexString = "";
1945 if ($function->{overloadedIndex} > 0) {
1946 $overloadedIndexString .= $function->{overloadedIndex};
1949 my $raisesExceptions = @{$function->raisesExceptions};
1950 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
1951 $raisesExceptions = 1;
1953 if (!$raisesExceptions) {
1954 foreach my $parameter (@{$function->parameters}) {
1955 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
1956 $raisesExceptions = 1;
1961 my @beforeArgumentList;
1962 my @afterArgumentList;
1963 push(@implContentInternals, <<END);
1964 static v8::Handle<v8::Value> constructor${overloadedIndexString}(const v8::Arguments& args)
1968 if ($function->{overloadedIndex} == 0) {
1969 push(@implContentInternals, GenerateArgumentsCountCheck($function, $interface));
1972 if ($raisesExceptions) {
1973 AddToImplIncludes("ExceptionCode.h");
1974 push(@implContentInternals, "\n");
1975 push(@implContentInternals, " ExceptionCode ec = 0;\n");
1978 # FIXME: Currently [Constructor(...)] does not yet support [Optional] arguments.
1979 # It just supports [Optional=DefaultIsUndefined] or [Optional=DefaultIsNullString].
1980 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
1981 push(@implContentInternals, $parameterCheckString);
1983 if ($interface->extendedAttributes->{"CallWith"} && $interface->extendedAttributes->{"CallWith"} eq "ScriptExecutionContext") {
1984 push(@beforeArgumentList, "context");
1985 push(@implContentInternals, <<END);
1987 ScriptExecutionContext* context = getScriptExecutionContext();
1991 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
1992 push(@afterArgumentList, "ec");
1997 foreach my $parameter (@{$function->parameters}) {
1998 last if $index eq $paramIndex;
1999 if ($replacements{$parameter->name}) {
2000 push(@argumentList, $replacements{$parameter->name});
2002 push(@argumentList, $parameter->name);
2007 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
2008 push(@implContentInternals, "\n");
2009 push(@implContentInternals, " RefPtr<${interfaceName}> impl = ${interfaceName}::create(${argumentString});\n");
2010 push(@implContentInternals, " v8::Handle<v8::Object> wrapper = args.Holder();\n");
2012 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2013 push(@implContentInternals, " if (ec)\n");
2014 push(@implContentInternals, " goto fail;\n");
2017 push(@implContentInternals, <<END);
2019 V8DOMWrapper::associateObjectWithWrapper(impl.release(), &V8${interfaceName}::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
2023 if ($raisesExceptions) {
2024 push(@implContentInternals, " fail:\n");
2025 push(@implContentInternals, " return setDOMException(ec, args.GetIsolate());\n");
2028 push(@implContentInternals, "}\n");
2029 push(@implContentInternals, "\n");
2032 sub GenerateConstructorCallback
2034 my $interface = shift;
2036 my $interfaceName = $interface->name;
2037 push(@implContent, "v8::Handle<v8::Value> V8${interfaceName}::constructorCallback(const v8::Arguments& args)\n");
2038 push(@implContent, "{\n");
2039 push(@implContent, GenerateFeatureObservation($interface->extendedAttributes->{"V8MeasureAs"}));
2040 push(@implContent, GenerateConstructorHeader());
2041 if (HasCustomConstructor($interface)) {
2042 push(@implContent, " return V8${interfaceName}::constructorCustom(args);\n");
2044 push(@implContent, " return ${interfaceName}V8Internal::constructor(args);\n");
2046 push(@implContent, "}\n\n");
2049 sub GenerateConstructor
2051 my $interface = shift;
2052 my $interfaceName = $interface->name;
2054 if (@{$interface->constructors} == 1) {
2055 GenerateSingleConstructorCallback($interface, @{$interface->constructors}[0]);
2057 foreach my $constructor (@{$interface->constructors}) {
2058 GenerateSingleConstructorCallback($interface, $constructor);
2060 GenerateOverloadedConstructorCallback($interface);
2064 sub GenerateEventConstructor
2066 my $interface = shift;
2067 my $interfaceName = $interface->name;
2069 AddToImplIncludes("Dictionary.h");
2070 push(@implContentInternals, <<END);
2071 static v8::Handle<v8::Value> constructor(const v8::Arguments& args)
2074 push(@implContentInternals, <<END);
2075 if (args.Length() < 1)
2076 return throwNotEnoughArgumentsError(args.GetIsolate());
2078 V8TRYCATCH_FOR_V8STRINGRESOURCE(V8StringResource<>, type, args[0]);
2079 ${interfaceName}Init eventInit;
2080 if (args.Length() >= 2) {
2081 V8TRYCATCH(Dictionary, options, Dictionary(args[1], args.GetIsolate()));
2082 if (!fill${interfaceName}Init(eventInit, options))
2083 return v8Undefined();
2086 RefPtr<${interfaceName}> event = ${interfaceName}::create(type, eventInit);
2088 v8::Handle<v8::Object> wrapper = args.Holder();
2089 V8DOMWrapper::associateObjectWithWrapper(event.release(), &V8${interfaceName}::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
2094 push(@implContent, <<END);
2095 bool fill${interfaceName}Init(${interfaceName}Init& eventInit, const Dictionary& options)
2099 foreach my $interfaceBase (@{$interface->parents}) {
2100 push(@implContent, <<END);
2101 if (!fill${interfaceBase}Init(eventInit, options))
2107 for (my $index = 0; $index < @{$interface->attributes}; $index++) {
2108 my $attribute = @{$interface->attributes}[$index];
2109 if ($attribute->signature->extendedAttributes->{"InitializedByEventConstructor"}) {
2110 my $attributeName = $attribute->signature->name;
2111 push(@implContent, " options.get(\"$attributeName\", eventInit.$attributeName);\n");
2115 push(@implContent, <<END);
2122 sub GenerateTypedArrayConstructor
2124 my $interface = shift;
2125 my $interfaceName = $interface->name;
2126 my $viewType = GetTypeNameOfExternalTypedArray($interface);
2127 my $type = $interface->extendedAttributes->{"TypedArray"};
2128 AddToImplIncludes("V8ArrayBufferViewCustom.h");
2130 push(@implContentInternals, <<END);
2131 static v8::Handle<v8::Value> constructor(const v8::Arguments& args)
2133 return constructWebGLArray<$interfaceName, V8${interfaceName}, $type>(args, &V8${interfaceName}::info, $viewType);
2139 sub GenerateNamedConstructor
2141 my $function = shift;
2142 my $interface = shift;
2144 my $interfaceName = $interface->name;
2145 my $v8InterfaceName = "V8$interfaceName";
2146 my $raisesExceptions = @{$function->raisesExceptions};
2147 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2148 $raisesExceptions = 1;
2150 if (!$raisesExceptions) {
2151 foreach my $parameter (@{$function->parameters}) {
2152 if ((!$parameter->extendedAttributes->{"Callback"} and TypeCanFailConversion($parameter)) or $parameter->extendedAttributes->{"IsIndex"}) {
2153 $raisesExceptions = 1;
2158 my $maybeObserveFeature = GenerateFeatureObservation($function->signature->extendedAttributes->{"V8MeasureAs"});
2160 my @beforeArgumentList;
2161 my @afterArgumentList;
2163 my $toActiveDOMObject = "0";
2164 if ($codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
2165 $toActiveDOMObject = "${v8InterfaceName}::toActiveDOMObject";
2168 my $toEventTarget = "0";
2169 if ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
2170 $toEventTarget = "${v8InterfaceName}::toEventTarget";
2173 AddToImplIncludes("Frame.h");
2174 push(@implContent, <<END);
2175 WrapperTypeInfo ${v8InterfaceName}Constructor::info = { ${v8InterfaceName}Constructor::GetTemplate, ${v8InterfaceName}::derefObject, $toActiveDOMObject, $toEventTarget, 0, ${v8InterfaceName}::installPerContextPrototypeProperties, 0, WrapperTypeObjectPrototype };
2177 static v8::Handle<v8::Value> ${v8InterfaceName}ConstructorCallback(const v8::Arguments& args)
2179 ${maybeObserveFeature}
2181 push(@implContent, GenerateConstructorHeader());
2182 push(@implContent, <<END);
2183 Document* document = currentDocument(BindingState::instance());
2185 // Make sure the document is added to the DOM Node map. Otherwise, the ${interfaceName} instance
2186 // may end up being the only node in the map and get garbage-collected prematurely.
2187 toV8(document, args.Holder(), args.GetIsolate());
2191 push(@implContent, GenerateArgumentsCountCheck($function, $interface));
2193 if ($raisesExceptions) {
2194 AddToImplIncludes("ExceptionCode.h");
2195 push(@implContent, "\n");
2196 push(@implContent, " ExceptionCode ec = 0;\n");
2199 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interfaceName);
2200 push(@implContent, $parameterCheckString);
2202 push(@beforeArgumentList, "document");
2204 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2205 push(@afterArgumentList, "ec");
2210 foreach my $parameter (@{$function->parameters}) {
2211 last if $index eq $paramIndex;
2212 if ($replacements{$parameter->name}) {
2213 push(@argumentList, $replacements{$parameter->name});
2215 push(@argumentList, $parameter->name);
2220 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
2221 push(@implContent, "\n");
2222 push(@implContent, " RefPtr<${interfaceName}> impl = ${interfaceName}::createForJSConstructor(${argumentString});\n");
2223 push(@implContent, " v8::Handle<v8::Object> wrapper = args.Holder();\n");
2225 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2226 push(@implContent, " if (ec)\n");
2227 push(@implContent, " goto fail;\n");
2230 push(@implContent, <<END);
2232 V8DOMWrapper::associateObjectWithWrapper(impl.release(), &${v8InterfaceName}Constructor::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
2236 if ($raisesExceptions) {
2237 push(@implContent, " fail:\n");
2238 push(@implContent, " return setDOMException(ec, args.GetIsolate());\n");
2241 push(@implContent, "}\n");
2243 push(@implContent, <<END);
2245 v8::Persistent<v8::FunctionTemplate> ${v8InterfaceName}Constructor::GetTemplate(v8::Isolate* isolate)
2247 static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
2248 if (!cachedTemplate.IsEmpty())
2249 return cachedTemplate;
2251 v8::HandleScope scope;
2252 v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(${v8InterfaceName}ConstructorCallback);
2254 v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
2255 instance->SetInternalFieldCount(${v8InterfaceName}::internalFieldCount);
2256 result->SetClassName(v8::String::NewSymbol("${interfaceName}"));
2257 result->Inherit(${v8InterfaceName}::GetTemplate(isolate));
2259 cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(isolate, result);
2260 return cachedTemplate;
2266 sub GenerateConstructorHeader
2268 my $content = <<END;
2269 if (!args.IsConstructCall())
2270 return throwTypeError("DOM object constructor cannot be called as a function.", args.GetIsolate());
2272 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
2273 return args.Holder();
2279 sub GenerateBatchedAttributeData
2281 my $interface = shift;
2282 my $attributes = shift;
2283 my $interfaceName = $interface->name;
2285 foreach my $attribute (@$attributes) {
2286 my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature);
2287 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2288 GenerateSingleBatchedAttribute($interfaceName, $attribute, ",", "");
2289 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2293 sub GenerateSingleBatchedAttribute
2295 my $interfaceName = shift;
2296 my $attribute = shift;
2297 my $delimiter = shift;
2299 my $attrName = $attribute->signature->name;
2300 my $attrExt = $attribute->signature->extendedAttributes;
2302 my $accessControl = "v8::DEFAULT";
2303 if ($attrExt->{"DoNotCheckSecurityOnGetter"}) {
2304 $accessControl = "v8::ALL_CAN_READ";
2305 } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) {
2306 $accessControl = "v8::ALL_CAN_WRITE";
2307 } elsif ($attrExt->{"DoNotCheckSecurity"}) {
2308 $accessControl = "v8::ALL_CAN_READ";
2309 if (!IsReadonly($attribute)) {
2310 $accessControl .= " | v8::ALL_CAN_WRITE";
2313 if ($attrExt->{"V8Unforgeable"}) {
2314 $accessControl .= " | v8::PROHIBITS_OVERWRITING";
2316 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
2318 my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attrExt) || "";
2319 if ($customAccessor eq "VALUE_IS_MISSING") {
2320 # use the naming convension, interface + (capitalize) attr name
2321 $customAccessor = $interfaceName . "::" . $attrName;
2326 my $propAttr = "v8::None";
2329 if ($attrExt->{"NotEnumerable"}) {
2330 $propAttr .= " | v8::DontEnum";
2332 if ($attrExt->{"V8Unforgeable"}) {
2333 $propAttr .= " | v8::DontDelete";
2336 my $on_proto = "0 /* on instance */";
2337 my $data = "0 /* no data */";
2340 if ($attribute->signature->type =~ /Constructor$/) {
2341 my $constructorType = $attribute->signature->type;
2342 $constructorType =~ s/Constructor$//;
2343 # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor.
2344 # We do not generate the header file for NamedConstructor of class XXXX,
2345 # since we generate the NamedConstructor declaration into the header file of class XXXX.
2346 if ($constructorType !~ /Constructor$/ || $attribute->signature->extendedAttributes->{"V8CustomConstructor"} || $attribute->signature->extendedAttributes->{"CustomConstructor"}) {
2347 AddToImplIncludes("V8${constructorType}.h", $attribute->signature->extendedAttributes->{"Conditional"});
2349 $data = "&V8${constructorType}::info";
2350 $getter = "${interfaceName}V8Internal::${interfaceName}ConstructorGetter";
2351 $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetterCallback";
2353 # Default Getter and Setter
2354 $getter = "${interfaceName}V8Internal::${attrName}AttrGetterCallback";
2355 $setter = "${interfaceName}V8Internal::${attrName}AttrSetterCallback";
2357 if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) {
2358 $setter = "${interfaceName}V8Internal::${interfaceName}ReplaceableAttrSetterCallback";
2362 # Read only attributes
2363 if (IsReadonly($attribute)) {
2367 # An accessor can be installed on the proto
2368 if ($attrExt->{"V8OnProto"}) {
2369 $on_proto = "1 /* on proto */";
2372 my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type .
2373 "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2375 push(@implContent, $indent . " \/\/ $commentInfo\n");
2376 push(@implContent, $indent . " {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n");
2379 sub IsStandardFunction
2381 my $interface = shift;
2382 my $function = shift;
2384 my $interfaceName = $interface->name;
2385 my $attrExt = $function->signature->extendedAttributes;
2386 return 0 if $attrExt->{"V8Unforgeable"};
2387 return 0 if $function->isStatic;
2388 return 0 if $attrExt->{"V8EnabledAtRuntime"};
2389 return 0 if $attrExt->{"V8EnabledPerContext"};
2390 return 0 if RequiresCustomSignature($function);
2391 return 0 if $attrExt->{"V8DoNotCheckSignature"};
2392 return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "DOMWindow"));
2393 return 0 if $attrExt->{"NotEnumerable"};
2394 return 0 if $attrExt->{"V8ReadOnly"};
2398 sub GenerateNonStandardFunction
2400 my $interface = shift;
2401 my $function = shift;
2403 my $interfaceName = $interface->name;
2404 my $attrExt = $function->signature->extendedAttributes;
2405 my $name = $function->signature->name;
2407 my $property_attributes = "v8::DontDelete";
2408 if ($attrExt->{"NotEnumerable"}) {
2409 $property_attributes .= " | v8::DontEnum";
2411 if ($attrExt->{"V8ReadOnly"}) {
2412 $property_attributes .= " | v8::ReadOnly";
2415 my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')";
2417 my $template = "proto";
2418 if ($attrExt->{"V8Unforgeable"}) {
2419 $template = "instance";
2421 if ($function->isStatic) {
2425 my $conditional = "";
2426 if ($attrExt->{"V8EnabledAtRuntime"}) {
2427 # Only call Set()/SetAccessor() if this method should be enabled
2428 my $enable_function = GetRuntimeEnableFunctionName($function->signature);
2429 $conditional = "if (${enable_function}())\n ";
2431 if ($attrExt->{"V8EnabledPerContext"}) {
2432 # Only call Set()/SetAccessor() if this method should be enabled
2433 my $enable_function = GetContextEnableFunction($function->signature);
2434 $conditional = "if (${enable_function}(impl->document()))\n ";
2437 if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCheckSecurity"}) {
2438 # Functions that are marked DoNotCheckSecurity are always readable but if they are changed
2439 # and then accessed on a different domain we do not return the underlying value but instead
2440 # return a new copy of the original function. This is achieved by storing the changed value
2441 # as hidden property.
2442 push(@implContent, <<END);
2445 ${conditional}$template->SetAccessor(v8::String::NewSymbol("$name"), ${interfaceName}V8Internal::${name}AttrGetterCallback, ${interfaceName}V8Internal::${interfaceName}DomainSafeFunctionSetter, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
2450 my $signature = "defaultSignature";
2451 if ($attrExt->{"V8DoNotCheckSignature"} || $function->isStatic) {
2452 $signature = "v8::Local<v8::Signature>()";
2455 if (RequiresCustomSignature($function)) {
2456 $signature = "${name}Signature";
2457 push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function));
2460 if ($property_attributes eq "v8::DontDelete") {
2461 $property_attributes = "";
2463 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
2466 if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
2467 die "This shouldn't happen: Intraface '$interfaceName' $commentInfo\n";
2470 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2471 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2472 push(@implContent, " ${conditional}$template->Set(v8::String::NewSymbol(\"$name\"), v8::FunctionTemplate::New(${interfaceName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature})$property_attributes);\n");
2473 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
2476 sub GenerateImplementationIndexer
2478 my $interface = shift;
2479 my $indexer = shift;
2480 my $interfaceName = $interface->name;
2481 my $v8InterfaceName = "V8$interfaceName";
2483 # FIXME: Figure out what NumericIndexedGetter is really supposed to do. Right now, it's only set on WebGL-related files.
2484 my $hasCustomSetter = $interface->extendedAttributes->{"CustomIndexedSetter"} && !$interface->extendedAttributes->{"NumericIndexedGetter"};
2485 my $hasGetter = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
2487 # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled,
2488 # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide
2489 # simplistic, mirrored indexer handling in addition to named property handling.
2490 my $isSpecialCase = exists $indexerSpecialCases{$interfaceName};
2491 if ($isSpecialCase) {
2493 if ($interface->extendedAttributes->{"CustomNamedSetter"}) {
2494 $hasCustomSetter = 1;
2498 my $hasEnumerator = !$isSpecialCase && $codeGenerator->InheritsInterface($interface, "Node");
2500 # FIXME: Find a way to not have to special-case HTMLOptionsCollection.
2501 if ($interfaceName eq "HTMLOptionsCollection") {
2510 AddToImplIncludes("V8Collection.h");
2513 $indexer = $codeGenerator->FindSuperMethod($interface, "item");
2516 my $indexerType = $indexer ? $indexer->type : 0;
2518 # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563).
2519 if ($interfaceName eq "WebKitCSSKeyframesRule") {
2520 $indexerType = "WebKitCSSKeyframeRule";
2523 if ($indexerType && !$hasCustomSetter) {
2524 if ($indexerType eq "DOMString") {
2525 my $conversion = $indexer->extendedAttributes->{"TreatReturnedNullStringAs"};
2526 if ($conversion && $conversion eq "Null") {
2527 push(@implContent, <<END);
2528 setCollectionStringOrUndefinedIndexedGetter<${interfaceName}>(desc);
2531 push(@implContent, <<END);
2532 setCollectionStringIndexedGetter<${interfaceName}>(desc);
2536 push(@implContent, <<END);
2537 setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc);
2539 # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type.
2540 AddToImplIncludes("V8${indexerType}.h");
2546 my $hasDeleter = $interface->extendedAttributes->{"CustomDeleteProperty"};
2547 my $setOn = "Instance";
2549 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2550 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2551 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2553 if ($interfaceName eq "DOMWindow") {
2554 $setOn = "Prototype";
2558 push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(${v8InterfaceName}::indexedPropertyGetter");
2559 push(@implContent, $hasCustomSetter ? ", ${v8InterfaceName}::indexedPropertySetter" : ", 0");
2560 push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment.
2561 push(@implContent, $hasDeleter ? ", ${v8InterfaceName}::indexedPropertyDeleter" : ", 0");
2562 push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator;
2563 push(@implContent, ");\n");
2566 sub GenerateImplementationNamedPropertyGetter
2568 my $interface = shift;
2569 my $namedPropertyGetter = shift;
2570 my $interfaceName = $interface->name;
2571 my $v8InterfaceName = "V8$interfaceName";
2572 my $hasCustomNamedGetter = $interface->extendedAttributes->{"CustomNamedGetter"} || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
2574 if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") {
2575 $hasCustomNamedGetter = 1;
2578 if ($interfaceName eq "HTMLDocument") {
2579 $hasCustomNamedGetter = 0;
2582 my $hasGetter = $interface->extendedAttributes->{"NamedGetter"} || $hasCustomNamedGetter;
2587 if (!$namedPropertyGetter) {
2588 $namedPropertyGetter = $codeGenerator->FindSuperMethod($interface, "namedItem");
2591 if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomNamedGetter) {
2592 AddToImplIncludes("V8Collection.h");
2593 my $type = $namedPropertyGetter->type;
2594 push(@implContent, <<END);
2595 setCollectionNamedGetter<${interfaceName}, ${type}>(desc);
2600 my $hasCustomNamedSetter = $interface->extendedAttributes->{"CustomNamedSetter"};
2601 my $hasDeleter = $interface->extendedAttributes->{"CustomDeleteProperty"};
2602 my $hasEnumerator = $interface->extendedAttributes->{"CustomEnumerateProperty"};
2603 my $setOn = "Instance";
2605 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow
2606 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
2607 # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set
2609 if ($interfaceName eq "DOMWindow") {
2610 $setOn = "Prototype";
2615 if ($interfaceName eq "HTMLPropertiesCollection") {
2616 push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8HTMLCollection::namedPropertyGetter, ");
2618 push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(${v8InterfaceName}::namedPropertyGetter, ");
2620 push(@implContent, $hasCustomNamedSetter ? "${v8InterfaceName}::namedPropertySetter, " : "0, ");
2621 # If there is a custom enumerator, there MUST be custom query to properly communicate property attributes.
2622 push(@implContent, $hasEnumerator ? "${v8InterfaceName}::namedPropertyQuery, " : "0, ");
2623 push(@implContent, $hasDeleter ? "${v8InterfaceName}::namedPropertyDeleter, " : "0, ");
2624 push(@implContent, $hasEnumerator ? "${v8InterfaceName}::namedPropertyEnumerator" : "0");
2625 push(@implContent, ");\n");
2628 sub GenerateImplementationCustomCall
2630 my $interface = shift;
2631 my $interfaceName = $interface->name;
2633 if ($interface->extendedAttributes->{"CustomCall"}) {
2634 push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n");
2638 sub GenerateImplementationMasqueradesAsUndefined
2640 my $interface = shift;
2641 if ($interface->extendedAttributes->{"MasqueradesAsUndefined"})
2643 push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n");
2647 sub GenerateImplementation
2650 my $interface = shift;
2651 my $interfaceName = $interface->name;
2652 my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface);
2653 my $v8InterfaceName = "V8$interfaceName";
2654 my $nativeType = GetNativeTypeForConversions($interface);
2655 my $vtableNameGnu = GetGnuVTableNameForInterface($interface);
2656 my $vtableRefGnu = GetGnuVTableRefForInterface($interface);
2657 my $vtableRefWin = GetWinVTableRefForInterface($interface);
2659 # - Add default header template
2660 push(@implContentHeader, GenerateImplementationContentHeader($interface));
2662 AddToImplIncludes("BindingState.h");
2663 AddToImplIncludes("ContextFeatures.h");
2664 AddToImplIncludes("RuntimeEnabledFeatures.h");
2665 AddToImplIncludes("V8Binding.h");
2666 AddToImplIncludes("V8DOMWrapper.h");
2668 AddIncludesForType($interfaceName);
2670 my $toActiveDOMObject = $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject") ? "${v8InterfaceName}::toActiveDOMObject" : "0";
2671 my $toEventTarget = $codeGenerator->InheritsExtendedAttribute($interface, "EventTarget") ? "${v8InterfaceName}::toEventTarget" : "0";
2672 my $rootForGC = NeedsCustomOpaqueRootForGC($interface) ? "${v8InterfaceName}::opaqueRootForGC" : "0";
2674 # Find the super descriptor.
2675 my $parentClass = "";
2676 my $parentClassTemplate = "";
2677 foreach (@{$interface->parents}) {
2679 AddToImplIncludes("V8${parent}.h");
2680 $parentClass = "V8" . $parent;
2681 $parentClassTemplate = $parentClass . "::GetTemplate(isolate)";
2685 push(@implContentInternals, <<END) if $vtableNameGnu;
2686 #if ENABLE(BINDING_INTEGRITY)
2688 #pragma warning(disable: 4483)
2689 extern "C" { extern void (*const ${vtableRefWin}[])(); }
2691 extern "C" { extern void* ${vtableNameGnu}[]; }
2693 #endif // ENABLE(BINDING_INTEGRITY)
2697 push(@implContentInternals, "namespace WebCore {\n\n");
2699 push(@implContentInternals, <<END) if $vtableNameGnu;
2700 #if ENABLE(BINDING_INTEGRITY)
2701 // This checks if a DOM object that is about to be wrapped is valid.
2702 // Specifically, it checks that a vtable of the DOM object is equal to
2703 // a vtable of an expected class.
2704 // Due to a dangling pointer, the DOM object you are wrapping might be
2705 // already freed or realloced. If freed, the check will fail because
2706 // a free list pointer should be stored at the head of the DOM object.
2707 // If realloced, the check will fail because the vtable of the DOM object
2708 // differs from the expected vtable (unless the same class of DOM object
2709 // is realloced on the slot).
2710 inline void checkTypeOrDieTrying(${nativeType}* object)
2712 void* actualVTablePointer = *(reinterpret_cast<void**>(object));
2714 void* expectedVTablePointer = reinterpret_cast<void*>(${vtableRefWin});
2716 void* expectedVTablePointer = ${vtableRefGnu};
2718 if (actualVTablePointer != expectedVTablePointer)
2721 #endif // ENABLE(BINDING_INTEGRITY)
2726 my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
2728 my $WrapperTypePrototype = $interface->isException ? "WrapperTypeErrorPrototype" : "WrapperTypeObjectPrototype";
2730 push(@implContentInternals, "WrapperTypeInfo ${v8InterfaceName}::info = { ${v8InterfaceName}::GetTemplate, ${v8InterfaceName}::derefObject, $toActiveDOMObject, $toEventTarget, $rootForGC, ${v8InterfaceName}::installPerContextPrototypeProperties, $parentClassInfo, $WrapperTypePrototype };\n\n");
2731 push(@implContentInternals, "namespace ${interfaceName}V8Internal {\n\n");
2733 push(@implContentInternals, "template <typename T> void V8_USE(T) { }\n\n");
2735 my $hasConstructors = 0;
2736 my $hasReplaceable = 0;
2738 # Generate property accessors for attributes.
2739 for (my $index = 0; $index < @{$interface->attributes}; $index++) {
2740 my $attribute = @{$interface->attributes}[$index];
2741 my $attrType = $attribute->signature->type;
2742 my $attrExt = $attribute->signature->extendedAttributes;
2744 # Generate special code for the constructor attributes.
2745 if ($attrType =~ /Constructor$/) {
2746 if (!HasCustomGetter($attrExt)) {
2747 $hasConstructors = 1;
2752 if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
2753 $attrExt->{"V8OnProto"} = 1;
2756 if ($attrType eq "SerializedScriptValue") {
2757 AddToImplIncludes("SerializedScriptValue.h");
2760 GenerateNormalAttrGetter($attribute, $interface);
2761 GenerateNormalAttrGetterCallback($attribute, $interface);
2763 if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) {
2764 $hasReplaceable = 1;
2765 } elsif (!IsReadonly($attribute)) {
2766 GenerateNormalAttrSetter($attribute, $interface);
2767 GenerateNormalAttrSetterCallback($attribute, $interface);
2771 if ($hasConstructors) {
2772 GenerateConstructorGetter($interface);
2775 if ($hasConstructors || $hasReplaceable) {
2776 GenerateReplaceableAttrSetter($interface);
2777 GenerateReplaceableAttrSetterCallback($interface);
2780 if (NeedsCustomOpaqueRootForGC($interface)) {
2781 GenerateOpaqueRootForGC($interface);
2784 if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne "DOMWindow") {
2785 GenerateSecurityCheckFunctions($interface);
2788 if ($interface->extendedAttributes->{"TypedArray"}) {
2789 my $viewType = GetTypeNameOfExternalTypedArray($interface);
2790 push(@implContent, <<END);
2791 v8::Handle<v8::Object> wrap($interfaceName* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
2794 v8::Handle<v8::Object> wrapper = ${v8InterfaceName}::createWrapper(impl, creationContext, isolate);
2795 if (!wrapper.IsEmpty())
2796 wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), $viewType, impl->length());
2804 my $namedPropertyGetter;
2805 my @enabledPerContextFunctions;
2806 my @normalFunctions;
2807 my $needsDomainSafeFunctionSetter = 0;
2808 # Generate methods for functions.
2809 foreach my $function (@{$interface->functions}) {
2810 GenerateFunction($function, $interface);
2811 if ($function->{overloadIndex} == @{$function->{overloads}}) {
2812 if ($function->{overloadIndex} > 1) {
2813 GenerateOverloadedFunction($function, $interface);
2815 GenerateFunctionCallback($function, $interface);
2818 if ($function->signature->name eq "item") {
2819 $indexer = $function->signature;
2822 if ($interfaceName eq "HTMLPropertiesCollection") {
2823 if ($function->signature->name eq "propertyNodeList") {
2824 $namedPropertyGetter = $function->signature;
2826 } elsif ($function->signature->name eq "namedItem") {
2827 $namedPropertyGetter = $function->signature;
2830 # If the function does not need domain security check, we need to
2831 # generate an access getter that returns different function objects
2832 # for different calling context.
2833 if ($interface->extendedAttributes->{"CheckSecurity"} && $function->signature->extendedAttributes->{"DoNotCheckSecurity"}) {
2834 if (!HasCustomMethod($function->signature->extendedAttributes) || $function->{overloadIndex} == 1) {
2835 GenerateDomainSafeFunctionGetter($function, $interfaceName);
2836 $needsDomainSafeFunctionSetter = 1;
2840 # Separate out functions that are enabled per context so we can process them specially.
2841 if ($function->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2842 push(@enabledPerContextFunctions, $function);
2844 push(@normalFunctions, $function);
2848 if ($needsDomainSafeFunctionSetter) {
2849 GenerateDomainSafeFunctionSetter($interfaceName);
2853 my $attributes = $interface->attributes;
2855 # For the DOMWindow interface we partition the attributes into the
2856 # ones that disallows shadowing and the rest.
2857 my @disallowsShadowing;
2858 # Also separate out attributes that are enabled at runtime so we can process them specially.
2859 my @enabledAtRuntimeAttributes;
2860 my @enabledPerContextAttributes;
2861 my @normalAttributes;
2862 foreach my $attribute (@$attributes) {
2864 if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8Unforgeable"}) {
2865 push(@disallowsShadowing, $attribute);
2866 } elsif ($attribute->signature->extendedAttributes->{"V8EnabledAtRuntime"}) {
2867 push(@enabledAtRuntimeAttributes, $attribute);
2868 } elsif ($attribute->signature->extendedAttributes->{"V8EnabledPerContext"}) {
2869 push(@enabledPerContextAttributes, $attribute);
2871 push(@normalAttributes, $attribute);
2874 $attributes = \@normalAttributes;
2875 # Put the attributes that disallow shadowing on the shadow object.
2876 if (@disallowsShadowing) {
2877 push(@implContent, "static const V8DOMConfiguration::BatchedAttribute shadowAttrs[] = {\n");
2878 GenerateBatchedAttributeData($interface, \@disallowsShadowing);
2879 push(@implContent, "};\n\n");
2882 my $has_attributes = 0;
2884 $has_attributes = 1;
2885 push(@implContent, "static const V8DOMConfiguration::BatchedAttribute ${v8InterfaceName}Attrs[] = {\n");
2886 GenerateBatchedAttributeData($interface, $attributes);
2887 push(@implContent, "};\n\n");
2890 # Setup table of standard callback functions
2891 my $num_callbacks = 0;
2892 my $has_callbacks = 0;
2893 foreach my $function (@normalFunctions) {
2894 # Only one table entry is needed for overloaded methods:
2895 next if $function->{overloadIndex} > 1;
2896 # Don't put any nonstandard functions into this table:
2897 next if !IsStandardFunction($interface, $function);
2898 if (!$has_callbacks) {
2900 push(@implContent, "static const V8DOMConfiguration::BatchedMethod ${v8InterfaceName}Methods[] = {\n");
2902 my $name = $function->signature->name;
2903 my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature);
2904 push(@implContent, "#if ${conditionalString}\n") if $conditionalString;
2905 push(@implContent, <<END);
2906 {"$name", ${interfaceName}V8Internal::${name}MethodCallback},
2908 push(@implContent, "#endif\n") if $conditionalString;
2911 push(@implContent, "};\n\n") if $has_callbacks;
2914 my $has_constants = 0;
2915 my @constantsEnabledAtRuntime;
2916 if (@{$interface->constants}) {
2918 push(@implContent, "static const V8DOMConfiguration::BatchedConstant ${v8InterfaceName}Consts[] = {\n");
2920 foreach my $constant (@{$interface->constants}) {
2921 my $name = $constant->name;
2922 my $value = $constant->value;
2923 my $attrExt = $constant->extendedAttributes;
2924 my $conditional = $attrExt->{"Conditional"};
2925 my $implementedBy = $attrExt->{"ImplementedBy"};
2926 if ($implementedBy) {
2927 AddToImplIncludes("${implementedBy}.h");
2929 if ($attrExt->{"V8EnabledAtRuntime"}) {
2930 push(@constantsEnabledAtRuntime, $constant);
2932 # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl
2933 # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we
2934 # handled this here, and converted it to a -1 constant in the c++ output.
2936 my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional);
2937 push(@implContent, "#if ${conditionalString}\n");
2939 push(@implContent, <<END);
2940 {"${name}", static_cast<signed int>($value)},
2942 push(@implContent, "#endif\n") if $conditional;
2945 if ($has_constants) {
2946 push(@implContent, "};\n\n");
2947 push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($interface));
2950 if (!HasCustomConstructor($interface)) {
2951 if ($interface->extendedAttributes->{"NamedConstructor"}) {
2952 GenerateNamedConstructor(@{$interface->constructors}[0], $interface);
2953 } elsif ($interface->extendedAttributes->{"Constructor"}) {
2954 GenerateConstructor($interface);
2955 } elsif ($codeGenerator->IsConstructorTemplate($interface, "Event")) {
2956 GenerateEventConstructor($interface);
2957 } elsif ($codeGenerator->IsConstructorTemplate($interface, "TypedArray")) {
2958 GenerateTypedArrayConstructor($interface);
2961 if (IsConstructable($interface)) {
2962 GenerateConstructorCallback($interface);
2965 push(@implContentInternals, "} // namespace ${interfaceName}V8Internal\n\n");
2967 my $access_check = "";
2968 if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne "DOMWindow") {
2969 $access_check = "instance->SetAccessCheckCallbacks(${interfaceName}V8Internal::namedSecurityCheck, ${interfaceName}V8Internal::indexedSecurityCheck, v8::External::New(&${v8InterfaceName}::info));";
2972 # For the DOMWindow interface, generate the shadow object template
2973 # configuration method.
2974 if ($interfaceName eq "DOMWindow") {
2975 push(@implContent, <<END);
2976 static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ, v8::Isolate* isolate)
2978 V8DOMConfiguration::batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, WTF_ARRAY_LENGTH(shadowAttrs), isolate);
2980 // Install a security handler with V8.
2981 templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheckCustom, V8DOMWindow::indexedSecurityCheckCustom, v8::External::New(&V8DOMWindow::info));
2982 templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
2988 if (!$parentClassTemplate) {
2989 $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()";
2992 # Generate the template configuration method
2993 push(@implContent, <<END);
2994 static v8::Persistent<v8::FunctionTemplate> Configure${v8InterfaceName}Template(v8::Persistent<v8::FunctionTemplate> desc, v8::Isolate* isolate)
2996 desc->ReadOnlyPrototype();
2998 v8::Local<v8::Signature> defaultSignature;
3000 if ($interface->extendedAttributes->{"V8EnabledAtRuntime"}) {
3001 my $enable_function = GetRuntimeEnableFunctionName($interface);
3002 push(@implContent, <<END);
3003 if (!${enable_function}())
3004 defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"\", $parentClassTemplate, ${v8InterfaceName}::internalFieldCount, 0, 0, 0, 0, isolate);
3008 push(@implContent, <<END);
3009 defaultSignature = V8DOMConfiguration::configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, ${v8InterfaceName}::internalFieldCount,
3011 # Set up our attributes if we have them
3012 if ($has_attributes) {
3013 push(@implContent, <<END);
3014 ${v8InterfaceName}Attrs, WTF_ARRAY_LENGTH(${v8InterfaceName}Attrs),
3017 push(@implContent, <<END);
3022 if ($has_callbacks) {
3023 push(@implContent, <<END);
3024 ${v8InterfaceName}Methods, WTF_ARRAY_LENGTH(${v8InterfaceName}Methods), isolate);
3027 push(@implContent, <<END);
3032 AddToImplIncludes("wtf/UnusedParam.h");
3033 push(@implContent, <<END);
3034 UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
3037 if (IsConstructable($interface)) {
3038 my $conditionalString = $codeGenerator->GenerateConstructorConditionalString($interface);
3039 push(@implContent, "#if $conditionalString\n") if $conditionalString;
3040 push(@implContent, " desc->SetCallHandler(${v8InterfaceName}::constructorCallback);\n");
3041 push(@implContent, "#endif // $conditionalString\n") if $conditionalString;
3044 if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has_constants) {
3045 push(@implContent, <<END);
3046 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
3047 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
3048 UNUSED_PARAM(instance); // In some cases, it will not be used.
3049 UNUSED_PARAM(proto); // In some cases, it will not be used.
3053 push(@implContent, " $access_check\n");
3055 # Setup the enable-at-runtime attrs if we have them
3056 foreach my $runtime_attr (@enabledAtRuntimeAttributes) {
3057 my $enable_function = GetRuntimeEnableFunctionName($runtime_attr->signature);
3058 my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_attr->signature);
3059 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3060 push(@implContent, " if (${enable_function}()) {\n");
3061 push(@implContent, " static const V8DOMConfiguration::BatchedAttribute attrData =\\\n");
3062 GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " ");
3063 push(@implContent, <<END);
3064 V8DOMConfiguration::configureAttribute(instance, proto, attrData, isolate);
3067 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3070 # Setup the enable-at-runtime constants if we have them
3071 foreach my $runtime_const (@constantsEnabledAtRuntime) {
3072 my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
3073 my $conditionalString = $codeGenerator->GenerateConditionalString($runtime_const);
3074 my $name = $runtime_const->name;
3075 my $value = $runtime_const->value;
3076 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3077 push(@implContent, " if (${enable_function}()) {\n");
3078 push(@implContent, <<END);
3079 static const V8DOMConfiguration::BatchedConstant constData = {"${name}", static_cast<signed int>(${value})};
3080 V8DOMConfiguration::batchConfigureConstants(desc, proto, &constData, 1, isolate);
3082 push(@implContent, " }\n");
3083 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3086 GenerateImplementationIndexer($interface, $indexer);
3087 GenerateImplementationNamedPropertyGetter($interface, $namedPropertyGetter);
3088 GenerateImplementationCustomCall($interface);
3089 GenerateImplementationMasqueradesAsUndefined($interface);
3091 # Define our functions with Set() or SetAccessor()
3092 my $total_functions = 0;
3093 foreach my $function (@normalFunctions) {
3094 # Only one accessor is needed for overloaded methods:
3095 next if $function->{overloadIndex} > 1;
3098 next if IsStandardFunction($interface, $function);
3099 GenerateNonStandardFunction($interface, $function);
3103 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
3105 if ($has_constants) {
3106 push(@implContent, <<END);
3107 V8DOMConfiguration::batchConfigureConstants(desc, proto, ${v8InterfaceName}Consts, WTF_ARRAY_LENGTH(${v8InterfaceName}Consts), isolate);
3112 if ($interfaceName eq "DOMWindow") {
3113 push(@implContent, <<END);
3115 proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
3116 desc->SetHiddenPrototype(true);
3117 instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount);
3118 // Set access check callbacks, but turned off initially.
3119 // When a context is detached from a frame, turn on the access check.
3120 // Turning on checks also invalidates inline caches of the object.
3121 instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheckCustom, V8DOMWindow::indexedSecurityCheckCustom, v8::External::New(&V8DOMWindow::info), false);
3124 if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerContext" or $interfaceName eq "SharedWorkerContext") {
3125 push(@implContent, <<END);
3126 desc->SetHiddenPrototype(true);
3129 if ($interfaceName eq "Location") {
3130 push(@implContent, <<END);
3132 // For security reasons, these functions are on the instance instead
3133 // of on the prototype object to ensure that they cannot be overwritten.
3134 instance->SetAccessor(v8::String::NewSymbol("reload"), V8Location::reloadAttrGetterCustom, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3135 instance->SetAccessor(v8::String::NewSymbol("replace"), V8Location::replaceAttrGetterCustom, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3136 instance->SetAccessor(v8::String::NewSymbol("assign"), V8Location::assignAttrGetterCustom, 0, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly));
3140 push(@implContent, <<END);
3142 // Custom toString template
3143 desc->Set(v8::String::NewSymbol("toString"), V8PerIsolateData::current()->toStringTemplate());
3147 v8::Persistent<v8::FunctionTemplate> ${v8InterfaceName}::GetRawTemplate(v8::Isolate* isolate)
3149 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
3150 V8PerIsolateData::TemplateMap::iterator result = data->rawTemplateMap().find(&info);
3151 if (result != data->rawTemplateMap().end())
3152 return result->value;
3154 v8::HandleScope handleScope;
3155 v8::Persistent<v8::FunctionTemplate> templ = createRawTemplate(isolate);
3156 data->rawTemplateMap().add(&info, templ);
3160 v8::Persistent<v8::FunctionTemplate> ${v8InterfaceName}::GetTemplate(v8::Isolate* isolate)
3162 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
3163 V8PerIsolateData::TemplateMap::iterator result = data->templateMap().find(&info);
3164 if (result != data->templateMap().end())
3165 return result->value;
3167 v8::HandleScope handleScope;
3168 v8::Persistent<v8::FunctionTemplate> templ =
3169 Configure${v8InterfaceName}Template(GetRawTemplate(isolate), isolate);
3170 data->templateMap().add(&info, templ);
3174 bool ${v8InterfaceName}::HasInstance(v8::Handle<v8::Value> value, v8::Isolate* isolate)
3176 return GetRawTemplate(isolate)->HasInstance(value);
3181 if (@enabledPerContextAttributes) {
3182 push(@implContent, <<END);
3183 void ${v8InterfaceName}::installPerContextProperties(v8::Handle<v8::Object> instance, ${nativeType}* impl, v8::Isolate* isolate)
3185 v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetPrototype());
3186 // When building QtWebkit with V8 this variable is unused when none of the features are enabled.
3187 UNUSED_PARAM(proto);
3190 # Setup the enable-by-settings attrs if we have them
3191 foreach my $runtimeAttr (@enabledPerContextAttributes) {
3192 my $enableFunction = GetContextEnableFunction($runtimeAttr->signature);
3193 my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeAttr->signature);
3194 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3195 push(@implContent, " if (${enableFunction}(impl->document())) {\n");
3196 push(@implContent, " static const V8DOMConfiguration::BatchedAttribute attrData =\\\n");
3197 GenerateSingleBatchedAttribute($interfaceName, $runtimeAttr, ";", " ");
3198 push(@implContent, <<END);
3199 V8DOMConfiguration::configureAttribute(instance, proto, attrData, isolate);
3201 push(@implContent, " }\n");
3202 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3204 push(@implContent, <<END);
3210 if (@enabledPerContextFunctions) {
3211 push(@implContent, <<END);
3212 void ${v8InterfaceName}::installPerContextPrototypeProperties(v8::Handle<v8::Object> proto, v8::Isolate* isolate)
3214 UNUSED_PARAM(proto);
3216 # Setup the enable-by-settings functions if we have them
3217 push(@implContent, <<END);
3218 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate(isolate));
3219 UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
3221 ScriptExecutionContext* context = toScriptExecutionContext(proto->CreationContext());
3224 foreach my $runtimeFunc (@enabledPerContextFunctions) {
3225 my $enableFunction = GetContextEnableFunction($runtimeFunc->signature);
3226 my $conditionalString = $codeGenerator->GenerateConditionalString($runtimeFunc->signature);
3227 push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString;
3228 push(@implContent, " if (context && context->isDocument() && ${enableFunction}(static_cast<Document*>(context))) {\n");
3229 my $name = $runtimeFunc->signature->name;
3230 push(@implContent, <<END);
3231 proto->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New(${interfaceName}V8Internal::${name}MethodCallback, v8Undefined(), defaultSignature)->GetFunction());
3233 push(@implContent, " }\n");
3234 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3237 push(@implContent, <<END);
3243 if ($codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
3244 # MessagePort is handled like an active dom object even though it doesn't inherit
3245 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
3246 my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)";
3247 push(@implContent, <<END);
3248 ActiveDOMObject* ${v8InterfaceName}::toActiveDOMObject(v8::Handle<v8::Object> object)
3250 return $returnValue;
3256 if ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) {
3257 push(@implContent, <<END);
3258 EventTarget* ${v8InterfaceName}::toEventTarget(v8::Handle<v8::Object> object)
3260 return toNative(object);
3266 if ($interfaceName eq "DOMWindow") {
3267 push(@implContent, <<END);
3268 v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate(v8::Isolate* isolate)
3270 static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache;
3271 if (V8DOMWindowShadowObjectCache.IsEmpty()) {
3272 V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(isolate, v8::ObjectTemplate::New());
3273 ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache, isolate);
3275 return V8DOMWindowShadowObjectCache;
3281 GenerateToV8Converters($interface, $v8InterfaceName, $nativeType);
3283 push(@implContent, <<END);
3284 void ${v8InterfaceName}::derefObject(void* object)
3286 static_cast<${nativeType}*>(object)->deref();
3289 } // namespace WebCore
3292 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
3293 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
3295 # We've already added the header for this file in implContentHeader, so remove
3296 # it from implIncludes to ensure we don't #include it twice.
3297 delete $implIncludes{"${v8InterfaceName}.h"};
3300 sub GenerateHeaderContentHeader
3302 my $interface = shift;
3303 my $v8InterfaceName = "V8" . $interface->name;
3304 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
3306 my @headerContentHeader = split("\r", $headerTemplate);
3308 push(@headerContentHeader, "\n#ifndef ${v8InterfaceName}" . "_h\n");
3309 push(@headerContentHeader, "#define ${v8InterfaceName}" . "_h\n\n");
3310 push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalString;
3311 return @headerContentHeader;
3314 sub GenerateImplementationContentHeader
3316 my $interface = shift;
3317 my $v8InterfaceName = "V8" . $interface->name;
3318 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
3320 my @implContentHeader = split("\r", $headerTemplate);
3322 push(@implContentHeader, "\n#include \"config.h\"\n");
3323 push(@implContentHeader, "#if ${conditionalString}\n") if $conditionalString;
3324 push(@implContentHeader, "#include \"${v8InterfaceName}.h\"\n\n");
3325 return @implContentHeader;
3328 sub GenerateCallbackHeader
3331 my $interface = shift;
3333 my $interfaceName = $interface->name;
3334 my $v8InterfaceName = "V8$interfaceName";
3337 # - Add default header template
3338 push(@headerContent, GenerateHeaderContentHeader($interface));
3340 my @unsortedIncludes = ();
3341 push(@unsortedIncludes, "#include \"ActiveDOMCallback.h\"");
3342 push(@unsortedIncludes, "#include \"$interfaceName.h\"");
3343 push(@unsortedIncludes, "#include \"ScopedPersistent.h\"");
3344 push(@unsortedIncludes, "#include \"WorldContextHandle.h\"");
3345 push(@unsortedIncludes, "#include <v8.h>");
3346 push(@unsortedIncludes, "#include <wtf/Forward.h>");
3347 push(@headerContent, join("\n", sort @unsortedIncludes));
3349 push(@headerContent, "\n\nnamespace WebCore {\n\n");
3350 push(@headerContent, "class ScriptExecutionContext;\n\n");
3351 push(@headerContent, "class $v8InterfaceName : public $interfaceName, public ActiveDOMCallback {\n");
3353 push(@headerContent, <<END);
3355 static PassRefPtr<${v8InterfaceName}> create(v8::Handle<v8::Value> value, ScriptExecutionContext* context)
3357 ASSERT(value->IsObject());
3359 return adoptRef(new ${v8InterfaceName}(v8::Handle<v8::Object>::Cast(value), context));
3362 virtual ~${v8InterfaceName}();
3367 my $numFunctions = @{$interface->functions};
3368 if ($numFunctions > 0) {
3369 push(@headerContent, " // Functions\n");
3370 foreach my $function (@{$interface->functions}) {
3371 my @params = @{$function->parameters};
3372 if (!$function->signature->extendedAttributes->{"Custom"} &&
3373 !(GetNativeType($function->signature->type) eq "bool")) {
3374 push(@headerContent, " COMPILE_ASSERT(false)");
3377 push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(");
3380 foreach my $param (@params) {
3381 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
3383 push(@headerContent, join(", ", @args));
3384 push(@headerContent, ");\n");
3388 push(@headerContent, <<END);
3390 virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }
3393 ${v8InterfaceName}(v8::Handle<v8::Object>, ScriptExecutionContext*);
3395 ScopedPersistent<v8::Object> m_callback;
3396 WorldContextHandle m_worldContext;
3401 push(@headerContent, "}\n\n");
3402 push(@headerContent, "#endif // $v8InterfaceName" . "_h\n\n");
3404 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
3405 push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString;
3408 sub GenerateCallbackImplementation
3411 my $interface = shift;
3412 my $interfaceName = $interface->name;
3413 my $v8InterfaceName = "V8$interfaceName";
3415 # - Add default header template
3416 push(@implContentHeader, GenerateImplementationContentHeader($interface));
3418 AddToImplIncludes("ScriptExecutionContext.h");
3419 AddToImplIncludes("V8Binding.h");
3420 AddToImplIncludes("V8Callback.h");
3422 push(@implContent, "#include <wtf/Assertions.h>\n\n");
3423 push(@implContent, "namespace WebCore {\n\n");
3424 push(@implContent, <<END);
3425 ${v8InterfaceName}::${v8InterfaceName}(v8::Handle<v8::Object> callback, ScriptExecutionContext* context)
3426 : ActiveDOMCallback(context)
3427 , m_callback(callback)
3428 , m_worldContext(UseCurrentWorld)
3432 ${v8InterfaceName}::~${v8InterfaceName}()
3439 my $numFunctions = @{$interface->functions};
3440 if ($numFunctions > 0) {
3441 push(@implContent, "// Functions\n");
3442 foreach my $function (@{$interface->functions}) {
3443 my @params = @{$function->parameters};
3444 if ($function->signature->extendedAttributes->{"Custom"} ||
3445 !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) {
3449 AddIncludesForType($function->signature->type);
3450 push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${v8InterfaceName}::" . $function->signature->name . "(");
3454 my $thisType = $function->signature->extendedAttributes->{"PassThisToCallback"};
3455 foreach my $param (@params) {
3456 my $paramName = $param->name;
3457 AddIncludesForType($param->type);
3458 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $paramName);
3459 if ($thisType and $thisType eq $param->type) {
3460 push(@argsCheck, <<END);
3461 ASSERT(${paramName});
3466 push(@implContent, join(", ", @args));
3468 push(@implContent, ")\n");
3469 push(@implContent, "{\n");
3470 push(@implContent, @argsCheck) if @argsCheck;
3471 push(@implContent, " if (!canInvokeCallback())\n");
3472 push(@implContent, " return true;\n\n");
3473 push(@implContent, " v8::HandleScope handleScope;\n\n");
3474 push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext);\n");
3475 push(@implContent, " if (v8Context.IsEmpty())\n");
3476 push(@implContent, " return true;\n\n");
3477 push(@implContent, " v8::Context::Scope scope(v8Context);\n\n");
3480 foreach my $param (@params) {
3481 my $paramName = $param->name;
3482 push(@implContent, " v8::Handle<v8::Value> ${paramName}Handle = " . NativeToJSValue($param, $paramName, "v8::Handle<v8::Object>()", "v8Context->GetIsolate()") . ";\n");
3483 push(@implContent, " if (${paramName}Handle.IsEmpty()) {\n");
3484 push(@implContent, " if (!isScriptControllerTerminating())\n");
3485 push(@implContent, " CRASH();\n");
3486 push(@implContent, " return true;\n");
3487 push(@implContent, " }\n");
3488 push(@args, " ${paramName}Handle");
3491 if (scalar(@args) > 0) {
3492 push(@implContent, "\n v8::Handle<v8::Value> argv[] = {\n");
3493 push(@implContent, join(",\n", @args));
3494 push(@implContent, "\n };\n\n");
3496 push(@implContent, "\n v8::Handle<v8::Value> *argv = 0;\n\n");
3498 push(@implContent, " bool callbackReturnValue = false;\n");
3500 foreach my $param (@params) {
3501 next if $param->type ne $thisType;
3502 my $paramName = $param->name;
3503 push(@implContent, " return !invokeCallback(m_callback.get(), v8::Handle<v8::Object>::Cast(${paramName}Handle), " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
3507 push(@implContent, " return !invokeCallback(m_callback.get(), " . scalar(@params) . ", argv, callbackReturnValue, scriptExecutionContext());\n");
3509 push(@implContent, "}\n");
3513 push(@implContent, "\n} // namespace WebCore\n\n");
3515 my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
3516 push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString;
3519 sub BaseInterfaceName
3521 my $interface = shift;
3523 while (@{$interface->parents}) {
3524 $interface = $codeGenerator->ParseInterface(@{$interface->parents}[0], 1);
3527 return $interface->name;
3530 sub GenerateToV8Converters
3532 my $interface = shift;
3533 my $v8InterfaceName = shift;
3534 my $nativeType = shift;
3535 my $interfaceName = $interface->name;
3537 if ($interface->extendedAttributes->{"V8NoWrapperCache"} || $interface->extendedAttributes->{"SuppressToJSObject"}) {
3541 AddToImplIncludes("Frame.h");
3543 my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
3544 my $baseType = BaseInterfaceName($interface);
3546 push(@implContent, <<END);
3548 v8::Handle<v8::Object> ${v8InterfaceName}::createWrapper(${createWrapperArgumentType} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
3551 ASSERT(DOMDataStore::getWrapper(impl.get(), isolate).IsEmpty());
3554 my $vtableNameGnu = GetGnuVTableNameForInterface($interface);
3555 push(@implContent, <<END) if $vtableNameGnu;
3557 #if ENABLE(BINDING_INTEGRITY)
3558 checkTypeOrDieTrying(impl.get());
3562 push(@implContent, <<END) if ($baseType ne $interfaceName);
3563 ASSERT(static_cast<void*>(static_cast<${baseType}*>(impl.get())) == static_cast<void*>(impl.get()));
3566 if ($codeGenerator->InheritsInterface($interface, "Document")) {
3567 push(@implContent, <<END);
3568 if (Frame* frame = impl->frame()) {
3569 if (frame->script()->initializeMainWorld()) {
3570 // initializeMainWorld may have created a wrapper for the object, retry from the start.
3571 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper(impl.get(), isolate);
3572 if (!wrapper.IsEmpty())
3579 push(@implContent, <<END);
3581 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, &info, impl.get(), isolate);
3582 if (UNLIKELY(wrapper.IsEmpty()))
3585 installPerContextProperties(wrapper, impl.get(), isolate);
3586 V8DOMWrapper::associateObjectWithWrapper(impl, &info, wrapper, isolate, hasDependentLifetime ? WrapperConfiguration::Dependent : WrapperConfiguration::Independent);
3592 sub GenerateSecurityCheckFunctions
3594 my $interface = shift;
3595 my $interfaceName = $interface->name;
3596 my $v8InterfaceName = "V8$interfaceName";
3598 push(@implContentInternals, <<END);
3599 bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>)
3601 $interfaceName* imp = ${v8InterfaceName}::toNative(host);
3602 return BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame(), DoNotReportSecurityError);
3605 bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>)
3607 $interfaceName* imp = ${v8InterfaceName}::toNative(host);
3608 return BindingSecurity::shouldAllowAccessToFrame(BindingState::instance(), imp->frame(), DoNotReportSecurityError);
3614 sub GetNativeTypeForConversions
3616 my $interface = shift;
3617 my $interfaceName = $interface->name;
3618 $interfaceName = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName) if $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName);
3619 return $interfaceName;
3622 # See http://refspecs.linux-foundation.org/cxxabi-1.83.html.
3623 sub GetGnuVTableRefForInterface
3625 my $interface = shift;
3626 my $vtableName = GetGnuVTableNameForInterface($interface);
3630 my $typename = GetNativeTypeForConversions($interface);
3631 my $offset = GetGnuVTableOffsetForType($typename);
3632 return "&" . $vtableName . "[" . $offset . "]";
3635 sub GetGnuVTableNameForInterface
3637 my $interface = shift;
3638 my $typename = GetNativeTypeForConversions($interface);
3639 my $templatePosition = index($typename, "<");
3640 return "" if $templatePosition != -1;
3641 return "" if GetImplementationLacksVTableForInterface($interface);
3642 return "" if GetV8SkipVTableValidationForInterface($interface);
3643 return "_ZTV" . GetGnuMangledNameForInterface($interface);
3646 sub GetGnuMangledNameForInterface
3648 my $interface = shift;
3649 my $typename = GetNativeTypeForConversions($interface);
3650 my $templatePosition = index($typename, "<");
3651 if ($templatePosition != -1) {
3654 my $mangledType = length($typename) . $typename;
3655 my $namespace = GetNamespaceForInterface($interface);
3656 my $mangledNamespace = "N" . length($namespace) . $namespace;
3657 return $mangledNamespace . $mangledType . "E";
3660 sub GetGnuVTableOffsetForType
3662 my $typename = shift;
3663 if ($typename eq "SVGAElement"
3664 || $typename eq "SVGCircleElement"
3665 || $typename eq "SVGClipPathElement"
3666 || $typename eq "SVGDefsElement"
3667 || $typename eq "SVGEllipseElement"
3668 || $typename eq "SVGForeignObjectElement"
3669 || $typename eq "SVGGElement"
3670 || $typename eq "SVGImageElement"
3671 || $typename eq "SVGLineElement"
3672 || $typename eq "SVGPathElement"
3673 || $typename eq "SVGPolyElement"
3674 || $typename eq "SVGPolygonElement"
3675 || $typename eq "SVGPolylineElement"
3676 || $typename eq "SVGRectElement"
3677 || $typename eq "SVGSVGElement"
3678 || $typename eq "SVGStyledLocatableElement"
3679 || $typename eq "SVGStyledTransformableElement"
3680 || $typename eq "SVGSwitchElement"
3681 || $typename eq "SVGTextElement"
3682 || $typename eq "SVGTransformable"
3683 || $typename eq "SVGUseElement") {
3689 # See http://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B_Name_Mangling.
3690 sub GetWinVTableRefForInterface
3692 my $interface = shift;
3693 my $vtableName = GetWinVTableNameForInterface($interface);
3694 return 0 if !$vtableName;
3695 return "__identifier(\"" . $vtableName . "\")";
3698 sub GetWinVTableNameForInterface
3700 my $interface = shift;
3701 my $typename = GetNativeTypeForConversions($interface);
3702 my $templatePosition = index($typename, "<");
3703 return "" if $templatePosition != -1;
3704 return "" if GetImplementationLacksVTableForInterface($interface);
3705 return "" if GetV8SkipVTableValidationForInterface($interface);
3706 return "??_7" . GetWinMangledNameForInterface($interface) . "6B@";
3709 sub GetWinMangledNameForInterface
3711 my $interface = shift;
3712 my $typename = GetNativeTypeForConversions($interface);
3713 my $namespace = GetNamespaceForInterface($interface);
3714 return $typename . "@" . $namespace . "@@";