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.
11 # Copyright (C) 2013, 2014 Samsung Electronics. All rights reserved.
13 # This library is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU Library General Public
15 # License as published by the Free Software Foundation; either
16 # version 2 of the License, or (at your option) any later version.
18 # This library is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # Library General Public License for more details.
23 # You should have received a copy of the GNU Library General Public License
24 # along with this library; see the file COPYING.LIB. If not, write to
25 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 # Boston, MA 02111-1307, USA.
32 # my $outer = new Block("Free Name 1", "namespace Foo {", "} // namespace Foo");
33 # $outer->add(" void foo() {}");
34 # my $inner = new Block("Free Name 2", "namespace Bar {", "} // namespace Bar");
35 # $inner->add(" void bar() {}");
36 # $outer->add($inner);
37 # print $outer->toString();
50 my $name = shift || "Anonymous block";
51 my $header = shift || "";
52 my $footer = shift || "";
56 "header" => [$header],
57 "footer" => [$footer],
60 bless $object, $package;
67 my $header = shift || "";
69 push(@{$object->{header}}, $header);
75 my $footer = shift || "";
77 push(@{$object->{footer}}, $footer);
83 my $content = shift || "";
85 push(@{$object->{contents}}, $content);
92 my $header = join "", @{$object->{header}};
93 my $footer = join "", @{$object->{footer}};
95 $code .= "/* BEGIN " . $object->{name} . " */\n" if $verbose;
96 $code .= $header . "\n" if $header;
97 for my $content (@{$object->{contents}}) {
98 if (ref($content) eq "Block") {
99 $code .= $content->toString();
104 $code .= $footer . "\n" if $footer;
105 $code .= "/* END " . $object->{name} . " */\n" if $verbose;
110 package code_generator_v8;
122 my $interfaceIdlFiles;
123 my $writeFileOnlyIfChanged;
126 # Cache of IDL file pathnames.
128 my $cachedInterfaces = {};
130 my %implIncludes = ();
131 my %headerIncludes = ();
133 # Header code structure:
134 # Root ... Copyright, include duplication check
135 # Conditional ... #if FEATURE ... #endif (to be removed soon)
143 # Implementation code structure:
145 # Conditional ... #if FEATURE ... #endif (to be removed soon)
148 # NameSpaceInternal ... namespace ${implClassName}V8Internal in case of non-callback
151 # The integer primitive types, a map from an IDL integer type to its
152 # binding-level type name.
154 # NOTE: For the unsigned types, the "UI" prefix is used (and not
155 # "Ui"), so as to match onto the naming of V8Binding conversion
156 # methods (and not the Typed Array naming scheme for unsigned types.)
157 my %integerTypeHash = ("byte" => "Int8",
161 "long long" => "Int64",
162 "unsigned short" => "UInt16",
163 "unsigned long" => "UInt32",
164 "unsigned long long" => "UInt64"
167 # Other primitive types
169 # Promise is not yet in the Web IDL spec but is going to be speced
170 # as primitive types in the future.
171 # Since V8 dosn't provide Promise primitive object currently,
172 # primitiveTypeHash doesn't contain Promise.
173 my %primitiveTypeHash = ("Date" => 1,
175 "DOMTimeStamp" => 1, # typedef unsigned long long
182 my %nonWrapperTypes = ("CompareHow" => 1,
185 "EventListener" => 1,
186 "MediaQueryListListener" => 1,
188 "SerializedScriptValue" => 1,
192 my %typedArrayHash = ("ArrayBuffer" => [],
193 "ArrayBufferView" => [],
194 "Uint8Array" => ["unsigned char", "v8::kExternalUnsignedByteArray"],
195 "Uint8ClampedArray" => ["unsigned char", "v8::kExternalPixelArray"],
196 "Uint16Array" => ["unsigned short", "v8::kExternalUnsignedShortArray"],
197 "Uint32Array" => ["unsigned int", "v8::kExternalUnsignedIntArray"],
198 "Int8Array" => ["signed char", "v8::kExternalByteArray"],
199 "Int16Array" => ["short", "v8::kExternalShortArray"],
200 "Int32Array" => ["int", "v8::kExternalIntArray"],
201 "Float32Array" => ["float", "v8::kExternalFloatArray"],
202 "Float64Array" => ["double", "v8::kExternalDoubleArray"],
205 my %domNodeTypes = ("Attr" => 1,
207 "CharacterData" => 1,
210 "DocumentFragment" => 1,
217 "ProcessingInstruction" => 1,
221 "TestInterfaceDocument" => 1,
222 "TestInterfaceNode" => 1,
226 my %callbackFunctionTypeHash = ();
228 my %enumTypeHash = ();
230 my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick" => 1,
231 "onerror" => 1, "onload" => 1, "onmousedown" => 1,
232 "onmouseenter" => 1, "onmouseleave" => 1,
233 "onmousemove" => 1, "onmouseout" => 1, "onmouseover" => 1,
234 "onmouseup" => 1, "onresize" => 1, "onscroll" => 1,
237 my %svgTypeNewPropertyImplementation = (
239 "SVGLengthList" => 1,
241 "SVGNumberList" => 1,
244 "SVGPreserveAspectRatio" => 1,
247 "SVGStringList" => 1,
250 my %svgTypeNeedingTearOff = (
251 "SVGAngle" => "SVGPropertyTearOff<SVGAngle>",
252 "SVGMatrix" => "SVGMatrixTearOff",
253 "SVGPathSegList" => "SVGPathSegListPropertyTearOff",
254 "SVGTransform" => "SVGPropertyTearOff<SVGTransform>",
255 "SVGTransformList" => "SVGTransformListPropertyTearOff"
258 my %svgTypeWithWritablePropertiesNeedingTearOff = (
262 # Default license header
263 my $licenseHeader = <<EOF;
265 * Copyright (C) 2013 Google Inc. All rights reserved.
267 * Redistribution and use in source and binary forms, with or without
268 * modification, are permitted provided that the following conditions are
271 * * Redistributions of source code must retain the above copyright
272 * notice, this list of conditions and the following disclaimer.
273 * * Redistributions in binary form must reproduce the above
274 * copyright notice, this list of conditions and the following disclaimer
275 * in the documentation and/or other materials provided with the
277 * * Neither the name of Google Inc. nor the names of its
278 * contributors may be used to endorse or promote products derived from
279 * this software without specific prior written permission.
281 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
282 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
283 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
284 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
285 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
286 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
287 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
288 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
289 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
290 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
291 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
294 // This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY!
303 $idlDocument = shift;
304 $idlDirectories = shift;
305 $preprocessor = shift;
307 $interfaceIdlFiles = shift;
308 $writeFileOnlyIfChanged = shift;
310 $sourceRoot = dirname(dirname(dirname(Cwd::abs_path($0))));
312 bless($reference, $object);
317 sub IDLFileForInterface
319 my $interfaceName = shift;
322 my @directories = map { $_ = "$sourceRoot/$_" if -d "$sourceRoot/$_"; $_ } @$idlDirectories;
323 push(@directories, ".");
326 foreach my $idlFile (@$interfaceIdlFiles) {
327 $idlFiles->{fileparse(basename($idlFile), ".idl")} = $idlFile;
331 $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/;
332 $File::Find::prune = 1 if /^\../;
334 find($wanted, @directories);
337 return $idlFiles->{$interfaceName};
342 my $interfaceName = shift;
344 if (exists $cachedInterfaces->{$interfaceName}) {
345 return $cachedInterfaces->{$interfaceName};
348 # Step #1: Find the IDL file associated with 'interface'
349 my $filename = IDLFileForInterface($interfaceName)
350 or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n");
352 print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceName\"\n" if $verbose;
354 # Step #2: Parse the found IDL file (in quiet mode).
355 my $parser = idl_parser->new(1);
356 my $document = $parser->Parse($filename, $preprocessor);
358 foreach my $interface (@{$document->interfaces}) {
359 if ($interface->name eq $interfaceName or $interface->isPartial) {
360 $cachedInterfaces->{$interfaceName} = $interface;
365 die("Could NOT find interface definition for $interfaceName in $filename");
368 sub GenerateInterface
371 my $interface = shift;
373 %callbackFunctionTypeHash = map { $_->name => $_ } @{$idlDocument->callbackFunctions};
374 %enumTypeHash = map { $_->name => $_->values } @{$idlDocument->enumerations};
375 my $v8ClassName = GetV8ClassName($interface);
376 my $defineName = $v8ClassName . "_h";
377 my $internalNamespace = GetImplName($interface) . "V8Internal";
379 my $conditionalString = GenerateConditionalString($interface);
380 my $conditionalIf = "";
381 my $conditionalEndif = "";
382 if ($conditionalString) {
383 $conditionalIf = "#if ${conditionalString}";
384 $conditionalEndif = "#endif // ${conditionalString}";
387 $header{root} = new Block("ROOT", "", "");
388 # FIXME: newlines should be generated by Block::toString().
389 $header{conditional} = new Block("Conditional", "$conditionalIf", $conditionalEndif ? "$conditionalEndif" : "");
390 $header{includes} = new Block("Includes", "", "");
391 $header{nameSpaceWebCore} = new Block("Namespace WebCore", "\nnamespace WebCore {\n", "}");
392 $header{class} = new Block("Class definition", "", "");
393 $header{classPublic} = new Block("Class public:", "public:", "");
394 $header{classPrivate} = new Block("Class private:", "private:", "");
396 $header{root}->add($header{conditional});
397 $header{conditional}->add($header{includes});
398 $header{conditional}->add($header{nameSpaceWebCore});
399 $header{nameSpaceWebCore}->add($header{class});
400 $header{class}->add($header{classPublic});
401 $header{class}->add($header{classPrivate});
403 # - Add default header template
404 $header{root}->addHeader($licenseHeader);
405 $header{root}->addHeader("#ifndef $defineName\n#define $defineName\n");
406 $header{root}->addFooter("#endif // $defineName");
408 $implementation{root} = new Block("ROOT", "", "");
409 $implementation{conditional} = new Block("Conditional", $conditionalIf, $conditionalEndif);
410 $implementation{includes} = new Block("Includes", "", "");
412 # FIXME: newlines should be generated by Block::toString().
413 my $nameSpaceWebCoreBegin = "namespace WebCore {\n";
414 my $nameSpaceWebCoreEnd = "} // namespace WebCore";
415 $nameSpaceWebCoreBegin = "$nameSpaceWebCoreBegin\n" unless $interface->isCallback;
416 $nameSpaceWebCoreBegin = "\n$nameSpaceWebCoreBegin" if $interface->isCallback;
417 $implementation{nameSpaceWebCore} = new Block("Namespace WebCore", $nameSpaceWebCoreBegin, $nameSpaceWebCoreEnd);
418 $implementation{nameSpaceInternal} = new Block("Internal namespace", "namespace $internalNamespace {\n", "} // namespace $internalNamespace\n");
420 $implementation{root}->add($implementation{conditional});
421 $implementation{conditional}->add($implementation{includes});
422 $implementation{conditional}->add($implementation{nameSpaceWebCore});
423 if (!$interface->isCallback) {
424 $implementation{nameSpaceWebCore}->add($implementation{nameSpaceInternal});
427 # - Add default header template
428 $implementation{root}->addHeader($licenseHeader);
429 $implementation{root}->addHeader("#include \"config.h\"");
430 $implementation{includes}->add("#include \"${v8ClassName}.h\"\n\n");
432 # Start actual generation
433 if ($interface->isCallback) {
434 $object->GenerateCallbackHeader($interface);
435 $object->GenerateCallbackImplementation($interface);
437 $object->GenerateHeader($interface);
438 $object->GenerateImplementation($interface);
442 sub AddToImplIncludes
445 $implIncludes{$header} = 1;
448 sub AddToHeaderIncludes
452 for my $include (@includes) {
453 $headerIncludes{$include} = 1;
457 sub AddIncludesForType
461 return if IsPrimitiveType($type) or IsEnumType($type) or $type eq "object";
463 $type = $1 if $type =~ /SVG\w+TearOff<(\w+)>/;
465 # Handle non-wrapper types explicitly
466 if ($type eq "any" || IsCallbackFunctionType($type)) {
467 AddToImplIncludes("bindings/v8/ScriptValue.h");
468 } elsif ($type eq "CompareHow") {
469 } elsif ($type eq "Dictionary") {
470 AddToImplIncludes("bindings/v8/Dictionary.h");
471 } elsif ($type eq "EventHandler") {
472 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h");
473 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
474 } elsif ($type eq "EventListener") {
475 AddToImplIncludes("bindings/v8/BindingSecurity.h");
476 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
477 AddToImplIncludes("core/frame/DOMWindow.h");
478 } elsif ($type eq "MediaQueryListListener") {
479 AddToImplIncludes("core/css/MediaQueryListListener.h");
480 } elsif ($type eq "Promise") {
481 AddToImplIncludes("bindings/v8/ScriptPromise.h");
482 } elsif ($type eq "SerializedScriptValue") {
483 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
484 } elsif (IsTypedArrayType($type)) {
485 AddToImplIncludes("bindings/v8/custom/V8${type}Custom.h");
486 } elsif (my $arrayType = GetArrayType($type)) {
487 AddIncludesForType($arrayType);
488 } elsif (my $sequenceType = GetSequenceType($type)) {
489 AddIncludesForType($sequenceType);
490 } elsif (IsUnionType($type)) {
491 for my $unionMemberType (@{$type->unionMemberTypes}) {
492 AddIncludesForType($unionMemberType);
495 AddToImplIncludes("V8${type}.h");
499 sub HeaderFilesForInterface
501 my $interfaceName = shift;
502 my $implClassName = shift;
505 if (IsPrimitiveType($interfaceName) or IsEnumType($interfaceName) or IsCallbackFunctionType($interfaceName)) {
506 # Not interface type, no header files
508 my $idlFilename = Cwd::abs_path(IDLFileForInterface($interfaceName)) or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n");
509 my $idlRelPath = File::Spec->abs2rel($idlFilename, $sourceRoot);
510 push(@includes, dirname($idlRelPath) . "/" . $implClassName . ".h");
515 sub NeedsVisitDOMWrapper
517 my $interface = shift;
518 return ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "VisitDOMWrapper") || $interface->extendedAttributes->{"SetWrapperReferenceFrom"} || $interface->extendedAttributes->{"SetWrapperReferenceTo"} || SVGTypeNeedsToHoldContextElement($interface->name);
521 sub GenerateVisitDOMWrapper
523 my $interface = shift;
524 my $implClassName = GetImplName($interface);
525 my $v8ClassName = GetV8ClassName($interface);
527 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "VisitDOMWrapper")) {
531 my $nativeType = GetNativeTypeForConversions($interface);
533 void ${v8ClassName}::visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate)
535 ${nativeType}* impl = fromInternalPointer(object);
537 my $needSetWrapperReferenceContext = SVGTypeNeedsToHoldContextElement($interface->name) || $interface->extendedAttributes->{"SetWrapperReferenceTo"};
538 if ($needSetWrapperReferenceContext) {
540 v8::Local<v8::Object> creationContext = v8::Local<v8::Object>::New(isolate, wrapper);
541 V8WrapperInstantiationScope scope(creationContext, isolate);
544 if (SVGTypeNeedsToHoldContextElement($interface->name)) {
545 AddToImplIncludes("V8SVGPathElement.h");
547 if (impl->contextElement()) {
548 if (!DOMDataStore::containsWrapper<V8SVGElement>(impl->contextElement(), isolate))
549 wrap(impl->contextElement(), creationContext, isolate);
550 DOMDataStore::setWrapperReference<V8SVGElement>(wrapper, impl->contextElement(), isolate);
554 for my $setReference (@{$interface->extendedAttributes->{"SetWrapperReferenceTo"}}) {
555 my $setReferenceType = $setReference->type;
556 my $setReferenceV8Type = "V8".$setReferenceType;
558 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($setReferenceType);
559 if ($svgPropertyType) {
560 $setReferenceType = $svgNativeType;
563 my $setReferenceName = $setReference->name;
565 AddIncludesForType($setReferenceType);
567 ${setReferenceType}* ${setReferenceName} = impl->${setReferenceName}();
568 if (${setReferenceName}) {
569 if (!DOMDataStore::containsWrapper<${setReferenceV8Type}>(${setReferenceName}, isolate))
570 wrap(${setReferenceName}, creationContext, isolate);
571 DOMDataStore::setWrapperReference<${setReferenceV8Type}>(wrapper, ${setReferenceName}, isolate);
576 my $isReachableMethod = $interface->extendedAttributes->{"SetWrapperReferenceFrom"};
577 if ($isReachableMethod) {
578 AddToImplIncludes("bindings/v8/V8GCController.h");
579 AddToImplIncludes("core/dom/Element.h");
581 if (Node* owner = impl->${isReachableMethod}()) {
582 Node* root = V8GCController::opaqueRootForGC(owner, isolate);
583 isolate->SetReferenceFromGroup(v8::UniqueId(reinterpret_cast<intptr_t>(root)), wrapper);
590 setObjectGroup(object, wrapper, isolate);
594 $implementation{nameSpaceWebCore}->add($code);
597 sub GetSVGPropertyTypes
599 my $implType = shift;
602 my $svgListPropertyType;
605 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/;
607 $svgNativeType = GetSVGTypeNeedingTearOff($implType);
608 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType;
610 # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType>
611 $svgNativeType = "$svgNativeType ";
613 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($implType);
614 if ($svgNativeType =~ /SVGPropertyTearOff/) {
615 $svgPropertyType = $svgWrappedNativeType;
616 AddToHeaderIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h");
617 } elsif ($svgNativeType =~ /SVGMatrixTearOff/) {
618 $svgPropertyType = $svgWrappedNativeType;
619 AddToHeaderIncludes("core/svg/properties/SVGMatrixTearOff.h");
620 AddToHeaderIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h");
621 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/ or $svgNativeType =~ /SVGTransformListPropertyTearOff/) {
622 $svgListPropertyType = $svgWrappedNativeType;
623 AddToHeaderIncludes("core/svg/properties/SVGAnimatedListPropertyTearOff.h");
624 } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) {
625 $svgListPropertyType = $svgWrappedNativeType;
626 AddToHeaderIncludes("core/svg/properties/SVGPathSegListPropertyTearOff.h");
629 return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
632 sub GetIndexedGetterFunction
634 my $interface = shift;
636 return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned long", 1);
639 sub GetIndexedSetterFunction
641 my $interface = shift;
643 return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned long", 2);
646 sub GetIndexedDeleterFunction
648 my $interface = shift;
650 return GetSpecialAccessorFunctionForType($interface, "deleter", "unsigned long", 1);
653 sub GetNamedGetterFunction
655 my $interface = shift;
656 return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1);
659 sub GetNamedSetterFunction
661 my $interface = shift;
662 return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString", 2);
665 sub GetNamedDeleterFunction
667 my $interface = shift;
668 return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString", 1);
671 sub GetSpecialAccessorFunctionForType
673 my $interface = shift;
675 my $firstParameterType = shift;
676 my $numberOfParameters = shift;
678 foreach my $function (@{$interface->functions}) {
679 my $specials = $function->specials;
680 my $specialExists = grep { $_ eq $special } @$specials;
681 my $parameters = $function->parameters;
682 if ($specialExists and scalar(@$parameters) == $numberOfParameters and $parameters->[0]->type eq $firstParameterType) {
690 sub GetV8StringResourceMode
692 my $extendedAttributes = shift;
694 # Blink uses the non-standard identifier NullString instead of Web IDL
695 # standard EmptyString, in [TreatNullAs=NullString] and [TreatUndefinedAs=NullString],
696 # and does not support [TreatUndefinedAs=Null] or [TreatUndefinedAs=Missing]
697 # https://sites.google.com/a/chromium.org/dev/blink/webidl/blink-idl-extended-attributes#TOC-TreatNullAs-a-p-TreatUndefinedAs-a-p-
699 if (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNullAs"} eq "NullString") and ($extendedAttributes->{"TreatUndefinedAs"} and $extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) {
700 $mode = "WithUndefinedOrNullCheck";
701 } elsif ($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNullAs"} eq "NullString") {
702 $mode = "WithNullCheck";
710 my $interface = shift;
712 my $interfaceName = $interface->name;
713 my $implClassName = GetImplName($interface);
714 my $v8ClassName = GetV8ClassName($interface);
716 LinkOverloadedFunctions($interface);
718 # Ensure the IsDOMNodeType function is in sync.
719 die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMNodeType($interfaceName) != InheritsInterface($interface, "Node");
721 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
723 my $parentInterface = $interface->parent;
724 AddToHeaderIncludes("V8${parentInterface}.h") if $parentInterface;
725 AddToHeaderIncludes("bindings/v8/WrapperTypeInfo.h");
726 AddToHeaderIncludes("bindings/v8/V8Binding.h");
727 AddToHeaderIncludes("bindings/v8/V8DOMWrapper.h");
728 AddToHeaderIncludes("heap/Handle.h");
729 AddToHeaderIncludes(HeaderFilesForInterface($interfaceName, $implClassName));
730 foreach my $headerInclude (sort keys(%headerIncludes)) {
731 $header{includes}->add("#include \"${headerInclude}\"\n");
734 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
735 if ($svgNativeType) {
736 if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
737 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n");
739 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n");
743 $header{nameSpaceWebCore}->addHeader("\nclass Dictionary;") if $interface->extendedAttributes->{"EventConstructor"};
745 my $nativeType = GetNativeTypeForConversions($interface);
746 if ($interface->extendedAttributes->{"NamedConstructor"}) {
747 $header{nameSpaceWebCore}->addHeader(<<END);
749 class V8${nativeType}Constructor {
751 static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWorldType);
752 static const WrapperTypeInfo wrapperTypeInfo;
757 $header{class}->addHeader("class $v8ClassName {");
758 $header{class}->addFooter("};");
760 $header{classPublic}->add(<<END);
761 static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*);
762 static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWorldType);
763 static ${nativeType}* toNative(v8::Handle<v8::Object> object)
765 return fromInternalPointer(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex));
767 static const WrapperTypeInfo wrapperTypeInfo;
770 $header{classPublic}->add(" static void derefObject(void*);\n");
772 if (NeedsVisitDOMWrapper($interface)) {
773 $header{classPublic}->add(" static void visitDOMWrapper(void*, const v8::Persistent<v8::Object>&, v8::Isolate*);\n");
776 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
777 $header{classPublic}->add(" static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n");
780 if (InheritsInterface($interface, "EventTarget")) {
781 $header{classPublic}->add(" static EventTarget* toEventTarget(v8::Handle<v8::Object>);\n");
784 if ($interfaceName eq "Window") {
785 $header{classPublic}->add(<<END);
786 static v8::Handle<v8::ObjectTemplate> getShadowObjectTemplate(v8::Isolate*, WrapperWorldType);
790 my @perContextEnabledFunctions;
791 foreach my $function (@{$interface->functions}) {
792 my $name = $function->name;
794 my $attrExt = $function->extendedAttributes;
796 if (HasCustomMethod($attrExt) && $function->{overloadIndex} == 1) {
797 my $conditionalString = GenerateConditionalString($function);
798 $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString;
799 $header{classPublic}->add(<<END);
800 static void ${name}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&);
802 $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString;
804 if ($attrExt->{"PerContextEnabled"}) {
805 push(@perContextEnabledFunctions, $function);
809 if (IsConstructable($interface)) {
810 $header{classPublic}->add(" static void constructorCallback(const v8::FunctionCallbackInfo<v8::Value>&);\n");
813 if (HasCustomConstructor($interface)) {
814 $header{classPublic}->add(" static void constructorCustom(const v8::FunctionCallbackInfo<v8::Value>&);\n");
817 my @perContextEnabledAttributes;
818 foreach my $attribute (@{$interface->attributes}) {
819 my $name = $attribute->name;
820 my $attrExt = $attribute->extendedAttributes;
821 my $conditionalString = GenerateConditionalString($attribute);
822 if (HasCustomGetter($attrExt) && !$attrExt->{"ImplementedBy"}) {
823 $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString;
824 $header{classPublic}->add(<<END);
825 static void ${name}AttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>&);
827 $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString;
829 if (HasCustomSetter($attribute) && !$attrExt->{"ImplementedBy"}) {
830 $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString;
831 $header{classPublic}->add(<<END);
832 static void ${name}AttributeSetterCustom(v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&);
834 $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString;
836 if ($attrExt->{"PerContextEnabled"}) {
837 push(@perContextEnabledAttributes, $attribute);
841 GenerateHeaderNamedAndIndexedPropertyAccessors($interface);
842 GenerateHeaderLegacyCallAsFunction($interface);
843 GenerateHeaderCustomInternalFieldIndices($interface);
847 if ($interface->parent) {
848 my $v8ParentClassName = "V8" . $interface->parent;
849 $toWrappedType = "${v8ParentClassName}::toInternalPointer(impl)";
850 $fromWrappedType = "static_cast<${nativeType}*>(${v8ParentClassName}::fromInternalPointer(object))";
852 $toWrappedType = "impl";
853 $fromWrappedType = "static_cast<${nativeType}*>(object)";
856 $header{classPublic}->add(<<END);
857 static inline void* toInternalPointer(${nativeType}* impl)
859 return $toWrappedType;
862 static inline ${nativeType}* fromInternalPointer(void* object)
864 return $fromWrappedType;
868 if ($interface->name eq "Window") {
869 $header{classPublic}->add(<<END);
870 static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
871 static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
875 if (@perContextEnabledAttributes) {
876 $header{classPublic}->add(<<END);
877 static void installPerContextEnabledProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*);
880 $header{classPublic}->add(<<END);
881 static void installPerContextEnabledProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*) { }
885 if (@perContextEnabledFunctions) {
886 $header{classPublic}->add(<<END);
887 static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isolate*);
890 $header{classPublic}->add(<<END);
891 static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isolate*) { }
895 if ($interfaceName eq "HTMLElement") {
896 $header{classPublic}->add(<<END);
897 friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
898 friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
900 } elsif ($interfaceName eq "SVGElement") {
901 $header{classPublic}->add(<<END);
902 friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
903 friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
904 friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
906 } elsif ($interfaceName eq "HTMLUnknownElement") {
907 $header{classPublic}->add(<<END);
908 friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
910 } elsif ($interfaceName eq "Element") {
911 $header{classPublic}->add(<<END);
912 // This is a performance optimization hack. See V8Element::wrap.
913 friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
916 $header{classPublic}->add("\n"); # blank line to separate classPrivate
918 my $customToV8 = ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "ToV8");
919 my $passRefPtrType = GetPassRefPtrType($interface);
921 $header{classPrivate}->add(<<END);
922 friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
923 static v8::Handle<v8::Object> createWrapper(${passRefPtrType}, v8::Handle<v8::Object> creationContext, v8::Isolate*);
927 $header{nameSpaceWebCore}->add(<<END);
930 class WrapperTypeTraits<${nativeType} > {
932 static const WrapperTypeInfo* wrapperTypeInfo() { return &${v8ClassName}::wrapperTypeInfo; }
937 $header{nameSpaceWebCore}->add(<<END);
940 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
942 template<class CallbackInfo>
943 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ${nativeType}* impl)
945 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
948 template<class CallbackInfo>
949 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, ${nativeType}* impl)
951 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
954 template<class CallbackInfo, class Wrappable>
955 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, ${nativeType}* impl, Wrappable*)
957 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
961 if (NeedsSpecialWrap($interface)) {
962 $header{nameSpaceWebCore}->add(<<END);
964 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*);
967 $header{nameSpaceWebCore}->add(<<END);
969 inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
972 ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl, isolate));
973 return ${v8ClassName}::createWrapper(impl, creationContext, isolate);
978 $header{nameSpaceWebCore}->add(<<END);
980 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
983 return v8::Null(isolate);
984 v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper<${v8ClassName}>(impl, isolate);
985 if (!wrapper.IsEmpty())
987 return wrap(impl, creationContext, isolate);
990 template<typename CallbackInfo>
991 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ${nativeType}* impl)
993 if (UNLIKELY(!impl)) {
994 v8SetReturnValueNull(callbackInfo);
997 if (DOMDataStore::setReturnValueFromWrapper<${v8ClassName}>(callbackInfo.GetReturnValue(), impl))
999 v8::Handle<v8::Object> wrapper = wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate());
1000 v8SetReturnValue(callbackInfo, wrapper);
1003 template<typename CallbackInfo>
1004 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, ${nativeType}* impl)
1006 ASSERT(worldType(callbackInfo.GetIsolate()) == MainWorld);
1007 if (UNLIKELY(!impl)) {
1008 v8SetReturnValueNull(callbackInfo);
1011 if (DOMDataStore::setReturnValueFromWrapperForMainWorld<${v8ClassName}>(callbackInfo.GetReturnValue(), impl))
1013 v8::Handle<v8::Value> wrapper = wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate());
1014 v8SetReturnValue(callbackInfo, wrapper);
1017 template<class CallbackInfo, class Wrappable>
1018 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, ${nativeType}* impl, Wrappable* wrappable)
1020 if (UNLIKELY(!impl)) {
1021 v8SetReturnValueNull(callbackInfo);
1024 if (DOMDataStore::setReturnValueFromWrapperFast<${v8ClassName}>(callbackInfo.GetReturnValue(), impl, callbackInfo.Holder(), wrappable))
1026 v8::Handle<v8::Object> wrapper = wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate());
1027 v8SetReturnValue(callbackInfo, wrapper);
1032 $header{nameSpaceWebCore}->add(<<END);
1034 inline v8::Handle<v8::Value> toV8($passRefPtrType impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
1036 return toV8(impl.get(), creationContext, isolate);
1039 template<class CallbackInfo>
1040 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, $passRefPtrType impl)
1042 v8SetReturnValue(callbackInfo, impl.get());
1045 template<class CallbackInfo>
1046 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, $passRefPtrType impl)
1048 v8SetReturnValueForMainWorld(callbackInfo, impl.get());
1051 template<class CallbackInfo, class Wrappable>
1052 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, $passRefPtrType impl, Wrappable* wrappable)
1054 v8SetReturnValueFast(callbackInfo, impl.get(), wrappable);
1059 if ($interface->extendedAttributes->{"EventConstructor"}) {
1060 $header{nameSpaceWebCore}->add("bool initialize${implClassName}(${implClassName}Init&, const Dictionary&, ExceptionState&, const v8::FunctionCallbackInfo<v8::Value>& info, const String& = \"\");\n\n");
1064 sub GetInternalFields
1066 my $interface = shift;
1068 my @customInternalFields = ();
1069 # Event listeners on DOM nodes are explicitly supported in the GC controller.
1070 if (!InheritsInterface($interface, "Node") &&
1071 InheritsInterface($interface, "EventTarget")) {
1072 push(@customInternalFields, "eventListenerCacheIndex");
1074 # Persistent handle is stored in the last internal field.
1075 # FIXME: Remove this internal field. Since we need either of a persistent handle
1076 # (if the object is in oilpan) or a C++ pointer to the DOM object (if the object is not in oilpan),
1077 # we can share the internal field between the two cases.
1078 if (IsWillBeGarbageCollectedType($interface->name)) {
1079 push(@customInternalFields, "persistentHandleIndex");
1081 return @customInternalFields;
1084 sub GenerateHeaderCustomInternalFieldIndices
1086 my $interface = shift;
1087 my @customInternalFields = GetInternalFields($interface);
1088 my $customFieldCounter = 0;
1089 foreach my $customInternalField (@customInternalFields) {
1090 $header{classPublic}->add(<<END);
1091 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
1093 $customFieldCounter++;
1095 $header{classPublic}->add(<<END);
1096 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
1100 sub GenerateHeaderNamedAndIndexedPropertyAccessors
1102 my $interface = shift;
1104 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
1105 my $hasCustomIndexedGetter = $indexedGetterFunction && $indexedGetterFunction->extendedAttributes->{"Custom"};
1107 my $indexedSetterFunction = GetIndexedSetterFunction($interface);
1108 my $hasCustomIndexedSetter = $indexedSetterFunction && $indexedSetterFunction->extendedAttributes->{"Custom"};
1110 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface);
1111 my $hasCustomIndexedDeleters = $indexedDeleterFunction && $indexedDeleterFunction->extendedAttributes->{"Custom"};
1113 my $namedGetterFunction = GetNamedGetterFunction($interface);
1114 my $hasCustomNamedGetter = $namedGetterFunction && HasCustomPropertyGetter($namedGetterFunction->extendedAttributes);
1116 my $namedSetterFunction = GetNamedSetterFunction($interface);
1117 my $hasCustomNamedSetter = $namedSetterFunction && $namedSetterFunction->extendedAttributes->{"Custom"};
1119 my $namedDeleterFunction = GetNamedDeleterFunction($interface);
1120 my $hasCustomNamedDeleter = $namedDeleterFunction && $namedDeleterFunction->extendedAttributes->{"Custom"};
1122 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction->extendedAttributes->{"NotEnumerable"};
1123 my $hasCustomNamedEnumerator = $namedEnumeratorFunction && ExtendedAttributeContains($namedGetterFunction->extendedAttributes->{"Custom"}, "PropertyEnumerator");
1124 my $hasCustomNamedQuery = $namedEnumeratorFunction && ExtendedAttributeContains($namedGetterFunction->extendedAttributes->{"Custom"}, "PropertyQuery");
1126 if ($hasCustomIndexedGetter) {
1127 $header{classPublic}->add(" static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);\n");
1130 if ($hasCustomIndexedSetter) {
1131 $header{classPublic}->add(" static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n");
1134 if ($hasCustomIndexedDeleters) {
1135 $header{classPublic}->add(" static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);\n");
1138 if ($hasCustomNamedGetter) {
1139 $header{classPublic}->add(" static void namedPropertyGetterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&);\n");
1142 if ($hasCustomNamedSetter) {
1143 $header{classPublic}->add(" static void namedPropertySetterCustom(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n");
1146 if ($hasCustomNamedQuery) {
1147 $header{classPublic}->add(" static void namedPropertyQueryCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer>&);\n");
1150 if ($hasCustomNamedDeleter) {
1151 $header{classPublic}->add(" static void namedPropertyDeleterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean>&);\n");
1154 if ($hasCustomNamedEnumerator) {
1155 $header{classPublic}->add(" static void namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>&);\n");
1159 sub GenerateHeaderLegacyCallAsFunction
1161 my $interface = shift;
1163 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "LegacyCallAsFunction")) {
1164 $header{classPublic}->add(" static void legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>&);\n");
1168 sub HasActivityLogging
1170 my $forMainWorldSuffix = shift;
1171 my $attrExt = shift;
1174 if (!$attrExt->{"ActivityLogging"}) {
1177 my $logAllAccess = ($attrExt->{"ActivityLogging"} =~ /^For/); # No prefix, starts with For*Worlds suffix
1178 my $logGetter = ($attrExt->{"ActivityLogging"} =~ /^Getter/);
1179 my $logSetter = ($attrExt->{"ActivityLogging"} =~ /^Setter/);
1180 my $logOnlyIsolatedWorlds = ($attrExt->{"ActivityLogging"} =~ /ForIsolatedWorlds$/);
1182 if ($logOnlyIsolatedWorlds && $forMainWorldSuffix eq "ForMainWorld") {
1185 return $logAllAccess || ($logGetter && $access eq "Getter") || ($logSetter && $access eq "Setter");
1190 my $interface = shift;
1192 return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"EventConstructor"};
1195 sub HasCustomConstructor
1197 my $interface = shift;
1199 return $interface->extendedAttributes->{"CustomConstructor"};
1204 my $attrExt = shift;
1205 my $custom = $attrExt->{"Custom"};
1206 return $custom && ($custom eq "VALUE_IS_MISSING" || $custom eq "Getter");
1211 my $attribute = shift;
1212 my $custom = $attribute->extendedAttributes->{"Custom"};
1213 return $custom && ($custom eq "VALUE_IS_MISSING" || $custom eq "Setter") && !IsReadonly($attribute);
1218 my $attrExt = shift;
1219 return $attrExt->{"Custom"};
1222 sub HasCustomPropertyGetter
1224 my $attrExt = shift;
1225 my $custom = $attrExt->{"Custom"};
1226 return $custom && ($custom eq "VALUE_IS_MISSING" || ExtendedAttributeContains($custom, "PropertyGetter"));
1231 my $attribute = shift;
1232 my $attrExt = $attribute->extendedAttributes;
1233 return $attribute->isReadOnly && !$attrExt->{"Replaceable"} && !$attrExt->{"PutForwards"};
1238 my $interface = shift;
1239 return "V8" . $interface->name;
1244 my $interfaceOrAttributeOrFunction = shift;
1245 return $interfaceOrAttributeOrFunction->extendedAttributes->{"ImplementedAs"} || $interfaceOrAttributeOrFunction->name;
1248 sub GetImplNameFromImplementedBy
1250 my $implementedBy = shift;
1252 my $interface = ParseInterface($implementedBy);
1254 return $interface->extendedAttributes->{"ImplementedAs"} || $implementedBy;
1257 sub GenerateDomainSafeFunctionGetter
1259 my $function = shift;
1260 my $interface = shift;
1261 my $forMainWorldSuffix = shift;
1263 my $implClassName = GetImplName($interface);
1264 my $v8ClassName = GetV8ClassName($interface);
1265 my $funcName = $function->name;
1267 my $functionLength = GetFunctionLength($function);
1268 my $signature = "v8::Signature::New(info.GetIsolate(), ${v8ClassName}::domTemplate(info.GetIsolate(), currentWorldType))";
1269 if ($function->extendedAttributes->{"DoNotCheckSignature"}) {
1270 $signature = "v8::Local<v8::Signature>()";
1273 my $newTemplateParams = "${implClassName}V8Internal::${funcName}MethodCallback${forMainWorldSuffix}, v8Undefined(), $signature";
1275 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1276 $implementation{nameSpaceInternal}->add(<<END);
1277 static void ${funcName}OriginSafeMethodGetter${forMainWorldSuffix}(const v8::PropertyCallbackInfo<v8::Value>& info)
1279 // This is only for getting a unique pointer which we can pass to privateTemplate.
1280 static int privateTemplateUniqueKey;
1281 WrapperWorldType currentWorldType = worldType(info.GetIsolate());
1282 V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate());
1283 v8::Handle<v8::FunctionTemplate> privateTemplate = data->privateTemplate(currentWorldType, &privateTemplateUniqueKey, $newTemplateParams, $functionLength);
1285 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::domTemplate(info.GetIsolate(), currentWorldType));
1286 if (holder.IsEmpty()) {
1287 // This is only reachable via |object.__proto__.func|, in which case it
1288 // has already passed the same origin security check
1289 v8SetReturnValue(info, privateTemplate->GetFunction());
1292 ${implClassName}* imp = ${v8ClassName}::toNative(holder);
1293 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), DoNotReportSecurityError)) {
1294 static int sharedTemplateUniqueKey;
1295 v8::Handle<v8::FunctionTemplate> sharedTemplate = data->privateTemplate(currentWorldType, &sharedTemplateUniqueKey, $newTemplateParams, $functionLength);
1296 v8SetReturnValue(info, sharedTemplate->GetFunction());
1300 v8::Local<v8::Value> hiddenValue = getHiddenValue(info.GetIsolate(), info.This(), "${funcName}");
1301 if (!hiddenValue.IsEmpty()) {
1302 v8SetReturnValue(info, hiddenValue);
1306 v8SetReturnValue(info, privateTemplate->GetFunction());
1310 $implementation{nameSpaceInternal}->add(<<END);
1311 static void ${funcName}OriginSafeMethodGetterCallback${forMainWorldSuffix}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)
1313 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
1314 ${implClassName}V8Internal::${funcName}OriginSafeMethodGetter${forMainWorldSuffix}(info);
1315 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
1321 sub GenerateDomainSafeFunctionSetter
1323 my $interface = shift;
1325 my $interfaceName = $interface->name();
1326 my $implClassName = GetImplName($interface);
1327 my $v8ClassName = GetV8ClassName($interface);
1329 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1330 $implementation{nameSpaceInternal}->add(<<END);
1331 static void ${implClassName}OriginSafeMethodSetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)
1333 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate())));
1334 if (holder.IsEmpty())
1336 ${implClassName}* imp = ${v8ClassName}::toNative(holder);
1337 v8::String::Utf8Value attributeName(name);
1338 ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "${interfaceName}", info.Holder(), info.GetIsolate());
1339 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), exceptionState)) {
1340 exceptionState.throwIfNeeded();
1344 setHiddenValue(info.GetIsolate(), info.This(), name, jsValue);
1347 static void ${implClassName}OriginSafeMethodSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)
1349 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter");
1350 ${implClassName}V8Internal::${implClassName}OriginSafeMethodSetter(name, jsValue, info);
1351 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
1357 sub GenerateConstructorGetter
1359 my $interface = shift;
1360 my $implClassName = GetImplName($interface);
1362 $implementation{nameSpaceInternal}->add(<<END);
1363 static void ${implClassName}ConstructorGetter(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)
1365 v8::Handle<v8::Value> data = info.Data();
1366 ASSERT(data->IsExternal());
1367 V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext());
1368 if (!perContextData)
1370 v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::unwrap(data)));
1376 sub GenerateFeatureObservation
1378 my $measureAs = shift;
1381 AddToImplIncludes("core/frame/UseCounter.h");
1382 return " UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::${measureAs});\n";
1388 sub GenerateDeprecationNotification
1390 my $deprecateAs = shift;
1392 AddToImplIncludes("core/frame/UseCounter.h");
1393 return " UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::${deprecateAs});\n";
1398 sub GenerateActivityLogging
1400 my $accessType = shift;
1401 my $interface = shift;
1402 my $propertyName = shift;
1404 my $interfaceName = $interface->name;
1406 AddToImplIncludes("bindings/v8/V8DOMActivityLogger.h");
1409 if ($accessType eq "Method") {
1411 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
1412 if (contextData && contextData->activityLogger()) {
1413 Vector<v8::Handle<v8::Value> > loggerArgs = toNativeArguments<v8::Handle<v8::Value> >(info, 0);
1414 contextData->activityLogger()->log("${interfaceName}.${propertyName}", info.Length(), loggerArgs.data(), "${accessType}");
1417 } elsif ($accessType eq "Setter") {
1419 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
1420 if (contextData && contextData->activityLogger()) {
1421 v8::Handle<v8::Value> loggerArg[] = { jsValue };
1422 contextData->activityLogger()->log("${interfaceName}.${propertyName}", 1, &loggerArg[0], "${accessType}");
1425 } elsif ($accessType eq "Getter") {
1427 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
1428 if (contextData && contextData->activityLogger())
1429 contextData->activityLogger()->log("${interfaceName}.${propertyName}", 0, 0, "${accessType}");
1432 die "Unrecognized activity logging access type";
1438 sub GenerateNormalAttributeGetterCallback
1440 my $attribute = shift;
1441 my $interface = shift;
1442 my $forMainWorldSuffix = shift;
1443 my $exposeJSAccessors = shift;
1445 my $implClassName = GetImplName($interface);
1446 my $v8ClassName = GetV8ClassName($interface);
1447 my $attrExt = $attribute->extendedAttributes;
1448 my $attrName = $attribute->name;
1450 my $conditionalString = GenerateConditionalString($attribute);
1452 $code .= "#if ${conditionalString}\n" if $conditionalString;
1454 if ($exposeJSAccessors) {
1455 $code .= "static void ${attrName}AttributeGetterCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n";
1457 $code .= "static void ${attrName}AttributeGetterCallback${forMainWorldSuffix}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
1460 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMGetter\");\n";
1461 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"});
1462 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"});
1463 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Getter")) {
1464 $code .= GenerateActivityLogging("Getter", $interface, "${attrName}");
1466 if (HasCustomGetter($attrExt)) {
1467 $code .= " ${v8ClassName}::${attrName}AttributeGetterCustom(info);\n";
1469 $code .= " ${implClassName}V8Internal::${attrName}AttributeGetter${forMainWorldSuffix}(info);\n";
1471 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
1473 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1476 $implementation{nameSpaceInternal}->add($code);
1479 sub GetCachedAttribute
1481 my $attribute = shift;
1482 my $attrExt = $attribute->extendedAttributes;
1483 if (($attribute->type eq "any" || $attribute->type eq "SerializedScriptValue") && $attrExt->{"CachedAttribute"}) {
1484 return $attrExt->{"CachedAttribute"};
1489 sub GenerateNormalAttributeGetter
1491 my $attribute = shift;
1492 my $interface = shift;
1493 my $forMainWorldSuffix = shift;
1494 my $exposeJSAccessors = shift;
1496 my $interfaceName = $interface->name;
1497 my $implClassName = GetImplName($interface);
1498 my $v8ClassName = GetV8ClassName($interface);
1499 my $attrExt = $attribute->extendedAttributes;
1500 my $attrName = $attribute->name;
1501 my $attrType = $attribute->type;
1502 my $attrCached = GetCachedAttribute($attribute);
1504 if (HasCustomGetter($attrExt)) {
1508 AssertNotSequenceType($attrType);
1509 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttributes, "");
1510 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName);
1512 my $conditionalString = GenerateConditionalString($attribute);
1514 $code .= "#if ${conditionalString}\n" if $conditionalString;
1515 if ($exposeJSAccessors) {
1516 $code .= "static void ${attrName}AttributeGetter${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n";
1518 $code .= "static void ${attrName}AttributeGetter${forMainWorldSuffix}(const v8::PropertyCallbackInfo<v8::Value>& info)\n";
1521 if ($svgNativeType) {
1522 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName);
1523 if ($svgWrappedNativeType =~ /List/) {
1525 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder());
1529 $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder());
1530 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
1531 $svgWrappedNativeType* imp = &impInstance;
1534 } elsif ($attrExt->{"OnPrototype"} || $attrExt->{"Unforgeable"}) {
1535 if ($interfaceName eq "Window") {
1537 v8::Handle<v8::Object> holder = info.Holder();
1540 # perform lookup first
1542 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate())));
1543 if (holder.IsEmpty())
1548 ${implClassName}* imp = ${v8ClassName}::toNative(holder);
1551 my $reflect = $attribute->extendedAttributes->{"Reflect"};
1552 my $url = $attribute->extendedAttributes->{"URL"};
1553 if ($reflect && !$url && InheritsInterface($interface, "Node") && $attrType eq "DOMString") {
1554 # Generate super-compact call for regular attribute getter:
1555 my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute);
1556 my $getterExpression = "imp->${functionName}(" . join(", ", @arguments) . ")";
1557 $code .= " Element* imp = V8Element::toNative(info.Holder());\n";
1558 if ($attribute->extendedAttributes->{"ReflectOnly"}) {
1559 $code .= " String resultValue = ${getterExpression};\n";
1560 $code .= GenerateReflectOnlyCheck($attribute->extendedAttributes, " ");
1561 $getterExpression = "resultValue";
1563 $code .= " v8SetReturnValueString(info, ${getterExpression}, info.GetIsolate());\n";
1565 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1567 $implementation{nameSpaceInternal}->add($code);
1569 # Skip the rest of the function!
1575 v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "${attrName}");
1576 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1577 if (!imp->$attrCached()) {
1578 v8::Handle<v8::Value> jsValue = getHiddenValue(info.GetIsolate(), info.Holder(), propertyName);
1579 if (!jsValue.IsEmpty()) {
1580 v8SetReturnValue(info, jsValue);
1586 if (!$attribute->isStatic && !$imp) {
1588 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1593 my $raisesException = $attribute->extendedAttributes->{"RaisesException"};
1594 my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_MISSING" or $raisesException eq "Getter");
1595 if ($useExceptions || $attribute->extendedAttributes->{"CheckSecurity"}) {
1596 $code .= " ExceptionState exceptionState(ExceptionState::GetterContext, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
1599 # Generate security checks if necessary
1600 if ($attribute->extendedAttributes->{"CheckSecurity"}) {
1601 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1602 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), imp->" . GetImplName($attribute) . "(), exceptionState)) {\n";
1603 $code .= " v8SetReturnValueNull(info);\n";
1604 $code .= " exceptionState.throwIfNeeded();\n";
1605 $code .= " return;\n";
1609 my $isNullable = $attribute->isNullable;
1611 $code .= " bool isNull = false;\n";
1615 my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute);
1616 push(@arguments, "isNull") if $isNullable;
1617 push(@arguments, "exceptionState") if $useExceptions;
1618 if ($attribute->extendedAttributes->{"ImplementedBy"}) {
1619 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
1620 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
1621 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName));
1622 unshift(@arguments, "imp") if !$attribute->isStatic;
1623 $functionName = "${implementedByImplName}::${functionName}";
1624 } elsif ($attribute->isStatic) {
1625 $functionName = "${implClassName}::${functionName}";
1627 $functionName = "imp->${functionName}";
1629 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"CallWith"}, " ", 0);
1631 unshift(@arguments, @$arg);
1632 $getterString = "${functionName}(" . join(", ", @arguments) . ")";
1635 if ($attribute->type eq "EventHandler" && $interface->name eq "Window") {
1636 $code .= " if (!imp->document())\n";
1637 $code .= " return;\n";
1640 if ($useExceptions || $isNullable) {
1641 if ($nativeType =~ /^V8StringResource/) {
1642 $code .= " " . ConvertToV8StringResource($attribute, $nativeType, "cppValue", $getterString) . ";\n";
1644 $code .= " $nativeType jsValue = $getterString;\n";
1645 $getterString = "jsValue";
1649 $code .= " if (isNull) {\n";
1650 $code .= " v8SetReturnValueNull(info);\n";
1651 $code .= " return;\n";
1655 if ($useExceptions) {
1656 if ($useExceptions) {
1657 $code .= " if (UNLIKELY(exceptionState.throwIfNeeded()))\n";
1658 $code .= " return;\n";
1661 if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) {
1662 $code .= " if (state.hadException()) {\n";
1663 $code .= " throwError(state.exception(), info.GetIsolate());\n";
1664 $code .= " return;\n";
1669 $expression = "jsValue";
1670 $expression .= ".release()" if (IsRefPtrType($attrType));
1672 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
1673 $expression = $getterString;
1674 # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly).
1675 $expression = "static_pointer_cast<SVGAnimatedEnumeration>($expression)" if $attrType eq "SVGAnimatedEnumeration";
1678 if (ShouldKeepAttributeAlive($interface, $attribute, $attrType)) {
1679 my $arrayType = GetArrayType($attrType);
1681 $code .= " v8SetReturnValue(info, v8Array(${getterString}, info.GetIsolate()));\n";
1683 $implementation{nameSpaceInternal}->add($code);
1687 # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already
1688 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
1689 my $nativeReturnType = GetNativeType($attrType);
1690 my $v8ReturnType = "V8" . $attrType;
1691 $code .= " $nativeReturnType result = ${getterString};\n";
1692 if ($forMainWorldSuffix) {
1693 $code .= " if (result && DOMDataStore::setReturnValueFromWrapper${forMainWorldSuffix}<${v8ReturnType}>(info.GetReturnValue(), result.get()))\n";
1695 $code .= " if (result && DOMDataStore::setReturnValueFromWrapper<${v8ReturnType}>(info.GetReturnValue(), result.get()))\n";
1697 $code .= " return;\n";
1698 $code .= " v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());\n";
1699 $code .= " if (!wrapper.IsEmpty()) {\n";
1700 $code .= " setHiddenValue(info.GetIsolate(), info.Holder(), \"${attrName}\", wrapper);\n";
1701 $code .= " v8SetReturnValue(info, wrapper);\n";
1704 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1706 $implementation{nameSpaceInternal}->add($code);
1710 if ((IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") and IsSVGTypeNeedingTearOff($attrType)) {
1711 AddToImplIncludes("V8$attrType.h");
1712 my $svgNativeType = GetSVGTypeNeedingTearOff($attrType);
1713 # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
1714 if ($forMainWorldSuffix eq "ForMainWorld") {
1715 $code .= " v8SetReturnValueForMainWorld(info, static_cast<$svgNativeType*>($expression));\n";
1717 $code .= " v8SetReturnValueFast(info, static_cast<$svgNativeType*>($expression), imp);\n";
1719 } elsif (IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$/) {
1720 AddToImplIncludes("V8$attrType.h");
1721 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h");
1722 my $tearOffType = GetSVGTypeNeedingTearOff($attrType);
1724 if (IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->extendedAttributes->{"Immutable"}) {
1725 my $getter = $expression;
1726 $getter =~ s/imp->//;
1727 $getter =~ s/\(\)//;
1729 my $updateMethod = "&${implClassName}::update" . FirstLetterToUpperCase($getter);
1731 my $selfIsTearOffType = IsSVGTypeNeedingTearOff($interfaceName);
1732 if ($selfIsTearOffType) {
1733 AddToImplIncludes("core/svg/properties/SVGMatrixTearOff.h");
1734 # FIXME: Don't create a new one everytime we access the matrix property. This means, e.g, === won't work.
1735 $wrappedValue = "WTF::getPtr(SVGMatrixTearOff::create(wrapper, $expression))";
1737 AddToImplIncludes("core/svg/properties/SVGStaticPropertyTearOff.h");
1738 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /;
1740 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expression, $updateMethod))";
1742 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
1743 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expression))";
1744 } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
1745 $wrappedValue = "WTF::getPtr($expression)";
1747 $wrappedValue = "WTF::getPtr(${tearOffType}::create($expression))";
1749 if ($forMainWorldSuffix eq "ForMainWorld") {
1750 $code .= " v8SetReturnValueForMainWorld(info, $wrappedValue);\n";
1752 $code .= " v8SetReturnValueFast(info, $wrappedValue, imp);\n";
1754 } elsif ($attrCached) {
1755 if ($attribute->type eq "SerializedScriptValue") {
1757 RefPtr<SerializedScriptValue> serialized = $getterString;
1758 ScriptValue jsValue = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::Null(info.GetIsolate()));
1759 setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, jsValue);
1760 v8SetReturnValue(info, jsValue);
1763 if (!$useExceptions && !$isNullable) {
1765 ScriptValue jsValue = $getterString;
1769 setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, jsValue.v8Value());
1770 v8SetReturnValue(info, jsValue.v8Value());
1773 } elsif ($attribute->type eq "EventHandler") {
1774 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h");
1775 # FIXME: Pass the main world ID for main-world-only getters.
1776 my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute);
1777 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
1778 if ($implementedBy) {
1779 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
1780 $functionName = "${implementedByImplName}::${functionName}";
1781 push(@arguments, "imp");
1783 $functionName = "imp->${functionName}";
1785 $code .= " EventListener* jsValue = ${functionName}(" . join(", ", @arguments) . ");\n";
1786 $code .= " v8SetReturnValue(info, jsValue ? v8::Handle<v8::Value>(V8AbstractEventListener::cast(jsValue)->getListenerObject(imp->executionContext())) : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())));\n";
1788 my $nativeValue = NativeToJSValue($attribute->type, $attribute->extendedAttributes, $expression, " ", "", "info.GetIsolate()", "info", "imp", $forMainWorldSuffix, "return");
1789 $code .= "${nativeValue}\n";
1792 $code .= "}\n"; # end of getter
1793 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1795 $implementation{nameSpaceInternal}->add($code);
1798 sub ShouldKeepAttributeAlive
1800 my ($interface, $attribute, $returnType) = @_;
1801 my $attrName = $attribute->name;
1803 # For readonly attributes (including Replaceable), as a general rule, for
1804 # performance reasons we keep the attribute wrapper alive while the owner
1805 # wrapper is alive, because the attribute never changes.
1806 return 0 if !IsWrapperType($returnType);
1807 return 0 if !IsReadonly($attribute) && !$attribute->extendedAttributes->{"Replaceable"};
1809 # However, there are a couple of exceptions.
1811 # Node lifetime is managed by object grouping.
1812 return 0 if InheritsInterface($interface, "Node");
1813 return 0 if IsDOMNodeType($returnType);
1815 # To avoid adding a reference to itself.
1816 # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove this hack
1817 # depending on the attribute name.
1818 return 0 if $attrName eq "self";
1820 # FIXME: Remove these hard-coded hacks.
1821 return 0 if $returnType eq "EventTarget";
1822 return 0 if $returnType eq "Window";
1823 return 0 if $returnType =~ /SVG/;
1824 return 0 if $returnType =~ /HTML/;
1829 sub GenerateReplaceableAttributeSetterCallback
1831 my $interface = shift;
1832 my $implClassName = GetImplName($interface);
1835 $code .= "static void ${implClassName}ReplaceableAttributeSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n";
1837 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"MeasureAs"});
1838 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"DeprecateAs"});
1839 $code .= GenerateCustomElementInvocationScopeIfNeeded($interface->extendedAttributes);
1840 if (HasActivityLogging("", $interface->extendedAttributes, "Setter")) {
1841 die "IDL error: ActivityLog attribute cannot exist on a ReplacableAttributeSetterCallback";
1843 $code .= " ${implClassName}V8Internal::${implClassName}ReplaceableAttributeSetter(name, jsValue, info);\n";
1845 $implementation{nameSpaceInternal}->add($code);
1848 sub GenerateReplaceableAttributeSetter
1850 my $interface = shift;
1852 my $interfaceName = $interface->name();
1853 my $implClassName = GetImplName($interface);
1854 my $v8ClassName = GetV8ClassName($interface);
1858 static void ${implClassName}ReplaceableAttributeSetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)
1861 if ($interface->extendedAttributes->{"CheckSecurity"}) {
1862 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1864 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1865 v8::String::Utf8Value attributeName(name);
1866 ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "${interfaceName}", info.Holder(), info.GetIsolate());
1867 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), exceptionState)) {
1868 exceptionState.throwIfNeeded();
1875 info.This()->ForceSet(name, jsValue);
1879 $implementation{nameSpaceInternal}->add($code);
1882 sub GenerateCustomElementInvocationScopeIfNeeded
1887 if ($ext->{"CustomElementCallbacks"} or $ext->{"Reflect"}) {
1888 AddToImplIncludes("core/dom/custom/CustomElementCallbackDispatcher.h");
1890 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
1896 sub GenerateNormalAttributeSetterCallback
1898 my $attribute = shift;
1899 my $interface = shift;
1900 my $forMainWorldSuffix = shift;
1901 my $exposeJSAccessors = shift;
1903 my $implClassName = GetImplName($interface);
1904 my $v8ClassName = GetV8ClassName($interface);
1905 my $attrExt = $attribute->extendedAttributes;
1906 my $attrName = $attribute->name;
1908 my $conditionalString = GenerateConditionalString($attribute);
1910 $code .= "#if ${conditionalString}\n" if $conditionalString;
1912 if ($exposeJSAccessors) {
1913 $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n";
1915 $code .= " v8::Local<v8::Value> jsValue = info[0];\n";
1917 $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSuffix}(v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n";
1920 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMSetter\");\n";
1921 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"});
1922 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"});
1923 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Setter")) {
1924 $code .= GenerateActivityLogging("Setter", $interface, "${attrName}");
1926 $code .= GenerateCustomElementInvocationScopeIfNeeded($attrExt);
1927 if (HasCustomSetter($attribute)) {
1928 $code .= " ${v8ClassName}::${attrName}AttributeSetterCustom(jsValue, info);\n";
1930 $code .= " ${implClassName}V8Internal::${attrName}AttributeSetter${forMainWorldSuffix}(jsValue, info);\n";
1932 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
1934 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1936 $implementation{nameSpaceInternal}->add($code);
1939 sub FindAttributeWithName
1941 my $interface = shift;
1942 my $attrName = shift;
1944 foreach my $attribute (@{$interface->attributes}) {
1945 if ($attribute->name eq $attrName) {
1951 sub GenerateNormalAttributeSetter
1953 my $attribute = shift;
1954 my $interface = shift;
1955 my $forMainWorldSuffix = shift;
1956 my $exposeJSAccessors = shift;
1958 my $interfaceName = $interface->name;
1959 my $implClassName = GetImplName($interface);
1960 my $v8ClassName = GetV8ClassName($interface);
1961 my $attrName = $attribute->name;
1962 my $attrExt = $attribute->extendedAttributes;
1963 my $attrType = $attribute->type;
1964 my $attrCached = GetCachedAttribute($attribute);
1966 if (HasCustomSetter($attribute)) {
1970 my $conditionalString = GenerateConditionalString($attribute);
1972 $code .= "#if ${conditionalString}\n" if $conditionalString;
1973 if ($exposeJSAccessors) {
1974 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info)\n";
1976 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n";
1980 my $raisesException = $attribute->extendedAttributes->{"RaisesException"};
1981 my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_MISSING" or $raisesException eq "Setter");
1982 my $hasStrictTypeChecking = 1 if ($interface->extendedAttributes->{"StrictTypeChecking"} || $attribute->extendedAttributes->{"StrictTypeChecking"}) && IsWrapperType($attrType); # Currently only actually check interface types
1984 # Can throw exceptions from accessors or during type conversion.
1985 my $isIntegerType = IsIntegerType($attribute->type);
1987 # We throw exceptions using 'ExceptionState' if the attribute explicitly
1988 # claims that exceptions may be raised, or if a strict type check might
1989 # fail, or if we're dealing with SVG, which does strange things with
1990 # tearoffs and read-only wrappers.
1991 if ($useExceptions or $hasStrictTypeChecking or GetSVGTypeNeedingTearOff($interfaceName) or GetSVGTypeNeedingTearOff($attrType) or $isIntegerType) {
1992 $code .= " ExceptionState exceptionState(ExceptionState::SetterContext, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
1995 # If the "StrictTypeChecking" extended attribute is present, and the
1996 # attribute's type is an interface type, then if the incoming value does not
1997 # implement that interface, a TypeError is thrown rather than silently
1998 # passing NULL to the C++ code.
1999 # Per the Web IDL and ECMAScript specifications, incoming values can always
2000 # be converted to both strings and numbers, so do not throw TypeError if the
2001 # attribute is of these types.
2002 if ($hasStrictTypeChecking) {
2003 $code .= " if (!isUndefinedOrNull(jsValue) && !V8${attrType}::hasInstance(jsValue, info.GetIsolate())) {\n";
2004 $code .= " exceptionState.throwTypeError(\"The provided value is not of type '${attrType}'.\");\n";
2005 $code .= " exceptionState.throwIfNeeded();\n";
2006 $code .= " return;\n";
2010 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName);
2011 if ($svgNativeType) {
2012 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName);
2013 if ($svgWrappedNativeType =~ /List$/) {
2015 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder());
2018 $code .= " $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder());\n";
2019 $code .= " if (wrapper->isReadOnly()) {\n";
2020 $code .= " exceptionState.throwDOMException(NoModificationAllowedError, \"The attribute is read-only.\");\n";
2021 $code .= " exceptionState.throwIfNeeded();\n";
2022 $code .= " return;\n";
2024 $code .= " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n";
2025 $code .= " $svgWrappedNativeType* imp = &impInstance;\n";
2027 } elsif ($attrExt->{"OnPrototype"}) {
2029 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
2031 } elsif($attrExt->{"PutForwards"}) {
2032 my $destinationAttrName = $attrExt->{"PutForwards"};
2033 my $destinationInterface = ParseInterface($attrType);
2034 die "[PutForwards=x] value must be a wrapper type" unless $destinationInterface;
2035 my $destinationAttribute = FindAttributeWithName($destinationInterface, $destinationAttrName);
2036 die "[PutForwards=x] could not find $destinationAttrName in interface $attrType" unless $destinationAttribute;
2038 ${implClassName}* proxyImp = ${v8ClassName}::toNative(info.Holder());
2039 ${attrType}* imp = proxyImp->${attrName}();
2043 # Override attribute and fall through to forward setter call.
2044 $attribute = $destinationAttribute;
2045 $attrName = $attribute->name;
2046 $attrType = $attribute->type;
2047 $attrExt = $attribute->extendedAttributes;
2049 my $reflect = $attribute->extendedAttributes->{"Reflect"};
2050 if ($reflect && InheritsInterface($interface, "Node") && $attrType eq "DOMString") {
2051 # Generate super-compact call for regular attribute setter:
2052 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect;
2053 my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeName);
2054 my $mode = GetV8StringResourceMode($attribute->extendedAttributes);
2055 AddToImplIncludes("${namespace}.h");
2056 $code .= " Element* imp = V8Element::toNative(info.Holder());\n";
2057 $code .= " V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<$mode>, cppValue, jsValue);\n";
2058 # Attr (not Attribute) used in content attributes
2059 $code .= " imp->setAttribute(${namespace}::${contentAttributeName}Attr, cppValue);\n";
2061 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2063 $implementation{nameSpaceInternal}->add($code);
2065 # Skip the rest of the function!
2068 if (!$attribute->isStatic) {
2070 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
2075 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttributes, "parameter");
2076 if ($attribute->type eq "EventHandler") {
2077 if ($interface->name eq "Window") {
2078 $code .= " if (!imp->document())\n";
2079 $code .= " return;\n";
2082 my $asSetterValue = 0;
2083 $code .= JSValueToNativeStatement($attribute->type, $attribute->extendedAttributes, $asSetterValue, "jsValue", "cppValue", " ", "info.GetIsolate()");
2086 if (IsEnumType($attrType)) {
2087 # setter ignores invalid enumeration values
2088 my @enumValues = ValidEnumValues($attrType);
2089 my @validEqualities = ();
2090 foreach my $enumValue (@enumValues) {
2091 push(@validEqualities, "string == \"$enumValue\"");
2093 my $enumValidationExpression = join(" || ", @validEqualities);
2095 String string = cppValue;
2096 if (!($enumValidationExpression))
2101 my $expression = "cppValue";
2102 my $returnType = $attribute->type;
2103 if (IsRefPtrType($returnType) && !GetArrayType($returnType)) {
2104 $expression = "WTF::getPtr(" . $expression . ")";
2107 $code .= GenerateCustomElementInvocationScopeIfNeeded($attribute->extendedAttributes);
2109 my $returnSvgNativeType = GetSVGTypeNeedingTearOff($returnType);
2110 if ($returnSvgNativeType) {
2113 exceptionState.throwTypeError(\"The provided value is not of type '$returnType'.\");
2114 exceptionState.throwIfNeeded();
2118 $expression = $expression . "->propertyReference()";
2121 if ($attribute->type eq "EventHandler") {
2122 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
2123 my $implementedByImplName;
2124 if ($implementedBy) {
2125 $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
2127 if (!InheritsInterface($interface, "Node")) {
2128 my $attrImplName = GetImplName($attribute);
2130 if ($implementedBy) {
2131 $attrImplName = "${implementedByImplName}::${attrImplName}";
2132 push(@arguments, "imp");
2134 $attrImplName = "imp->${attrImplName}";
2136 $code .= " moveEventListenerToNewWrapper(info.Holder(), ${attrImplName}(" . join(", ", @arguments) . "), jsValue, ${v8ClassName}::eventListenerCacheIndex, info.GetIsolate());\n";
2138 my ($functionName, @arguments) = SetterExpression($interfaceName, $attribute);
2139 if ($implementedBy) {
2140 $functionName = "${implementedByImplName}::${functionName}";
2141 push(@arguments, "imp");
2143 $functionName = "imp->${functionName}";
2145 if (($interfaceName eq "Window" or $interfaceName eq "WorkerGlobalScope") and $attribute->name eq "onerror") {
2146 AddToImplIncludes("bindings/v8/V8ErrorHandler.h");
2147 push(@arguments, "V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(jsValue, true, info.GetIsolate())");
2149 push(@arguments, "V8EventListenerList::getEventListener(jsValue, true, ListenerFindOrCreate)");
2151 $code .= " ${functionName}(" . join(", ", @arguments) . ");\n";
2153 my ($functionName, @arguments) = SetterExpression($interfaceName, $attribute);
2154 push(@arguments, $expression);
2155 push(@arguments, "exceptionState") if $useExceptions;
2156 if ($attribute->extendedAttributes->{"ImplementedBy"}) {
2157 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
2158 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
2159 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName));
2160 unshift(@arguments, "imp") if !$attribute->isStatic;
2161 $functionName = "${implementedByImplName}::${functionName}";
2162 } elsif ($attribute->isStatic) {
2163 $functionName = "${implClassName}::${functionName}";
2165 $functionName = "imp->${functionName}";
2167 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"SetterCallWith"} || $attribute->extendedAttributes->{"CallWith"}, " ", 1);
2169 unshift(@arguments, @$arg);
2170 $code .= " ${functionName}(" . join(", ", @arguments) . ");\n";
2173 if ($useExceptions) {
2174 $code .= " exceptionState.throwIfNeeded();\n";
2177 if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) {
2178 $code .= " if (state.hadException())\n";
2179 $code .= " throwError(state.exception(), info.GetIsolate());\n";
2182 if ($svgNativeType) {
2183 if ($useExceptions) {
2184 $code .= " if (!exceptionState.hadException())\n";
2185 $code .= " wrapper->commitChange();\n";
2187 $code .= " wrapper->commitChange();\n";
2193 deleteHiddenValue(info.GetIsolate(), info.Holder(), "${attrName}"); // Invalidate the cached value.
2197 $code .= "}\n"; # end of setter
2198 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2200 $implementation{nameSpaceInternal}->add($code);
2203 sub NullOrOptionalCheck
2205 my $parameter = shift;
2208 # If undefined is passed for an optional argument, the argument should be
2209 # treated as missing; otherwise undefined is not allowed.
2210 if ($parameter->isNullable) {
2211 if ($parameter->isOptional) {
2212 return "isUndefinedOrNull($value)";
2214 return "${value}->IsNull()";
2216 if ($parameter->isOptional) {
2217 return "${value}->IsUndefined()";
2221 sub GenerateParametersCheckExpression
2223 my $numParameters = shift;
2224 my $function = shift;
2226 my @andExpression = ();
2227 push(@andExpression, "info.Length() == $numParameters");
2228 my $parameterIndex = 0;
2229 foreach my $parameter (@{$function->parameters}) {
2230 last if $parameterIndex >= $numParameters;
2231 my $value = "info[$parameterIndex]";
2232 my $type = $parameter->type;
2234 my $undefinedOrNullCheck = NullOrOptionalCheck($parameter, $value);
2236 # Only DOMString, wrapper types, and (to some degree) non-wrapper types
2239 # FIXME: If distinguishing non-primitive type from primitive type,
2240 # (e.g., sequence<DOMString> from DOMString or Dictionary from double)
2241 # the non-primitive type must appear *first* in the IDL file,
2242 # since we're not adding a check to primitive types.
2243 # This can be avoided if compute overloads for whole overload set at
2244 # once, rather than one method at a time, but that requires a complete
2245 # rewrite of this algorithm.
2247 # For DOMString with StrictTypeChecking only Null, Undefined and Object
2248 # are accepted for compatibility. Otherwise, no restrictions are made to
2249 # match the non-overloaded behavior.
2251 # FIXME: Implement WebIDL overload resolution algorithm.
2252 # https://code.google.com/p/chromium/issues/detail?id=293561
2253 if ($type eq "DOMString") {
2254 if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
2255 push(@andExpression, "isUndefinedOrNull(${value}) || ${value}->IsString() || ${value}->IsObject()");
2257 } elsif (IsCallbackInterface($parameter->type)) {
2258 # For Callbacks only checks if the value is null or function.
2259 push(@andExpression, "${value}->IsNull() || ${value}->IsFunction()");
2260 } elsif (GetArrayOrSequenceType($type)) {
2261 if ($parameter->isNullable) {
2262 push(@andExpression, "${value}->IsNull() || ${value}->IsArray()");
2264 push(@andExpression, "${value}->IsArray()");
2266 } elsif (IsWrapperType($type)) {
2267 if ($parameter->isNullable) {
2268 push(@andExpression, "${value}->IsNull() || V8${type}::hasInstance($value, info.GetIsolate())");
2270 push(@andExpression, "V8${type}::hasInstance($value, info.GetIsolate())");
2272 } elsif ($nonWrapperTypes{$type}) {
2273 # Non-wrapper types are just objects: we don't distinguish type
2274 if ($undefinedOrNullCheck) {
2275 push(@andExpression, "$undefinedOrNullCheck || ${value}->IsObject()");
2277 push(@andExpression, "${value}->IsObject()");
2283 @andExpression = map { "($_)" } @andExpression;
2284 my $res = "(" . join(" && ", @andExpression) . ")";
2288 # As per Web IDL specification, the length of a function Object is
2289 # its number of mandatory parameters.
2290 sub GetFunctionLength
2292 my $function = shift;
2294 my $numMandatoryParams = 0;
2295 foreach my $parameter (@{$function->parameters}) {
2296 # Abort as soon as we find the first optional parameter as no mandatory
2297 # parameter can follow an optional one.
2298 last if $parameter->isOptional;
2299 $numMandatoryParams++;
2301 return $numMandatoryParams;
2304 sub GenerateFunctionParametersCheck
2306 my $function = shift;
2308 my @orExpression = ();
2309 my $numParameters = 0;
2310 my $hasVariadic = 0;
2311 my $numMandatoryParams = @{$function->parameters};
2312 foreach my $parameter (@{$function->parameters}) {
2313 if ($parameter->isOptional) {
2314 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
2315 $numMandatoryParams--;
2317 if ($parameter->isVariadic) {
2323 if (!$hasVariadic) {
2324 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function));
2326 return ($numMandatoryParams, join(" || ", @orExpression));
2329 sub GenerateOverloadedFunction
2331 my $function = shift;
2332 my $interface = shift;
2333 my $forMainWorldSuffix = shift;
2335 # Generate code for choosing the correct overload to call. Overloads are
2336 # chosen based on the total number of arguments passed and the type of
2337 # values passed in non-primitive argument slots. When more than a single
2338 # overload is applicable, precedence is given according to the order of
2339 # declaration in the IDL.
2341 my $name = $function->name;
2342 my $interfaceName = $interface->name;
2343 my $implClassName = GetImplName($interface);
2345 my $conditionalString = GenerateConditionalString($function);
2346 my $leastNumMandatoryParams = 255;
2349 $code .= "#if ${conditionalString}\n\n" if $conditionalString;
2351 static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)
2354 foreach my $overload (@{$function->{overloads}}) {
2355 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($overload);
2356 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
2357 $code .= " if ($parametersCheck) {\n";
2358 my $overloadedIndexString = $overload->{overloadIndex};
2359 $code .= " ${name}${overloadedIndexString}Method${forMainWorldSuffix}(info);\n";
2360 $code .= " return;\n";
2363 if ($leastNumMandatoryParams >= 1) {
2364 $code .= " ExceptionState exceptionState(ExceptionState::ExecutionContext, \"${name}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
2365 $code .= " if (UNLIKELY(info.Length() < $leastNumMandatoryParams)) {\n";
2366 $code .= " exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments($leastNumMandatoryParams, info.Length()));\n";
2367 $code .= " exceptionState.throwIfNeeded();\n";
2368 $code .= " return;\n";
2371 exceptionState.throwTypeError(\"No function was found that matched the signature provided.\");
2372 exceptionState.throwIfNeeded();
2376 throwTypeError(ExceptionMessages::failedToExecute(\"${name}\", \"${interfaceName}\", \"No function was found that matched the signature provided.\"), info.GetIsolate());
2380 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
2381 $implementation{nameSpaceInternal}->add($code);
2384 sub GenerateFunctionCallback
2386 my $function = shift;
2387 my $interface = shift;
2388 my $forMainWorldSuffix = shift;
2390 my $implClassName = GetImplName($interface);
2391 my $v8ClassName = GetV8ClassName($interface);
2392 my $name = $function->name;
2398 my $conditionalString = GenerateConditionalString($function);
2400 $code .= "#if ${conditionalString}\n" if $conditionalString;
2402 static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)
2405 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n";
2406 $code .= GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"});
2407 $code .= GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"});
2408 if (HasActivityLogging($forMainWorldSuffix, $function->extendedAttributes, "Access")) {
2409 $code .= GenerateActivityLogging("Method", $interface, "${name}");
2411 if (HasCustomMethod($function->extendedAttributes)) {
2412 $code .= " ${v8ClassName}::${name}MethodCustom(info);\n";
2414 $code .= " ${implClassName}V8Internal::${name}Method${forMainWorldSuffix}(info);\n";
2416 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
2418 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2420 $implementation{nameSpaceInternal}->add($code);
2423 sub GenerateFunction
2425 my $function = shift;
2426 my $interface = shift;
2427 my $forMainWorldSuffix = shift;
2429 my $interfaceName = $interface->name;
2430 my $implClassName = GetImplName($interface);
2431 my $v8ClassName = GetV8ClassName($interface);
2432 my $name = $function->name;
2433 my $unoverloadedName = $function->name;
2434 my $implName = GetImplName($function);
2435 my $funcExt = $function->extendedAttributes;
2437 # Add includes for types even if custom
2438 my $returnType = $function->type;
2439 AddIncludesForType($returnType);
2440 foreach my $parameter (@{$function->parameters}) {
2441 my $paramType = $parameter->type;
2442 AddIncludesForType($paramType);
2445 if (HasCustomMethod($funcExt) || $name eq "") {
2449 if (@{$function->{overloads}} > 1) {
2450 # Append a number to an overloaded method's name to make it unique:
2451 $name = $name . $function->{overloadIndex};
2454 my $conditionalString = GenerateConditionalString($function);
2456 $code .= "#if ${conditionalString}\n" if $conditionalString;
2457 $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n";
2460 # We throw exceptions using 'ExceptionState' for a function if:
2461 # - it explicitly claims that exceptions may be raised (or should be if type checks fail.)
2462 # - event listeners.
2463 # - security-checking.
2464 # - weird SVG stuff.
2465 # - takes a parameter that might raise an exception on conversion.
2467 my $isEventListener = $name eq "addEventListener" || $name eq "removeEventListener";
2468 my $isEventDispatcher = $name eq "dispatchEvent";
2469 my $isSecurityCheckNecessary = $interface->extendedAttributes->{"CheckSecurity"} && !$function->extendedAttributes->{"DoNotCheckSecurity"};
2470 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
2471 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName);
2472 my $isNonListSVGType = $svgNativeType && !($interfaceName =~ /List$/);
2474 my $hasExceptionState = $raisesExceptions || $isEventListener || $isSecurityCheckNecessary || $isNonListSVGType || HasExceptionRaisingParameter($function);
2475 if ($hasExceptionState) {
2476 $code .= " ExceptionState exceptionState(ExceptionState::ExecutionContext, \"${unoverloadedName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
2479 if ($isEventListener || $isEventDispatcher) {
2480 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2481 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
2482 AddToImplIncludes("core/frame/DOMWindow.h");
2484 EventTarget* impl = ${v8ClassName}::toNative(info.Holder());
2485 if (DOMWindow* window = impl->toDOMWindow()) {
2486 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window->frame(), exceptionState)) {
2487 exceptionState.throwIfNeeded();
2490 if (!window->document())
2495 if ($isEventListener) {
2496 my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only";
2497 my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()";
2498 my $hiddenValueAction = ($name eq "addEventListener") ? "addHiddenValueToArray" : "removeHiddenValueFromArray";
2501 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(info[1], false, ListenerFind${lookupType});
2503 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, eventName, info[0]);
2504 impl->${implName}(eventName, listener${passRefPtrHandling}, info[2]->BooleanValue());
2505 if (!impl->toNode())
2506 ${hiddenValueAction}(info.Holder(), info[1], ${v8ClassName}::eventListenerCacheIndex, info.GetIsolate());
2510 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2512 $implementation{nameSpaceInternal}->add($code);
2516 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionState);
2518 if ($svgNativeType) {
2519 my $nativeClassName = GetNativeType($interfaceName);
2520 if ($interfaceName =~ /List$/) {
2521 $code .= " $nativeClassName imp = ${v8ClassName}::toNative(info.Holder());\n";
2523 AddToImplIncludes("core/dom/ExceptionCode.h");
2524 $code .= " $nativeClassName wrapper = ${v8ClassName}::toNative(info.Holder());\n";
2525 $code .= " if (wrapper->isReadOnly()) {\n";
2526 $code .= " exceptionState.throwDOMException(NoModificationAllowedError, \"The object is read-only.\");\n";
2527 $code .= " exceptionState.throwIfNeeded();\n";
2528 $code .= " return;\n";
2530 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName);
2531 $code .= " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n";
2532 $code .= " $svgWrappedNativeType* imp = &impInstance;\n";
2534 } elsif (!$function->isStatic) {
2536 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
2540 $code .= GenerateCustomElementInvocationScopeIfNeeded($funcExt);
2542 # Check domain security if needed
2543 if ($isSecurityCheckNecessary) {
2544 # We have not find real use cases yet.
2545 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2547 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), exceptionState)) {
2548 exceptionState.throwIfNeeded();
2554 if ($function->extendedAttributes->{"CheckSecurity"}) {
2555 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2556 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), imp->" . GetImplName($function) . "(exceptionState), exceptionState)) {\n";
2557 $code .= " v8SetReturnValueNull(info);\n";
2558 $code .= " exceptionState.throwIfNeeded();\n";
2559 $code .= " return;\n";
2564 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, $forMainWorldSuffix, $hasExceptionState);
2565 $code .= $parameterCheckString;
2567 # Build the function call string.
2568 $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interface, $forMainWorldSuffix, $hasExceptionState, %replacements);
2570 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2572 $implementation{nameSpaceInternal}->add($code);
2575 sub GenerateCallWith
2577 my $callWith = shift;
2578 return ([], "") unless $callWith;
2580 my $returnVoid = shift;
2581 my $function = shift;
2585 if (ExtendedAttributeContains($callWith, "ScriptState")) {
2586 $code .= $indent . "ScriptState* currentState = ScriptState::current();\n";
2587 $code .= $indent . "if (!currentState)\n";
2588 $code .= $indent . " return" . ($returnVoid ? "" : " v8Undefined()") . ";\n";
2589 $code .= $indent . "ScriptState& state = *currentState;\n";
2590 push(@callWithArgs, "&state");
2591 AddToImplIncludes("bindings/v8/ScriptState.h");
2593 if (ExtendedAttributeContains($callWith, "ExecutionContext")) {
2594 $code .= $indent . "ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());\n";
2595 push(@callWithArgs, "scriptContext");
2597 if ($function and ExtendedAttributeContains($callWith, "ScriptArguments")) {
2598 $code .= $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(info, " . @{$function->parameters} . "));\n";
2599 push(@callWithArgs, "scriptArguments.release()");
2600 AddToImplIncludes("bindings/v8/ScriptCallStackFactory.h");
2601 AddToImplIncludes("core/inspector/ScriptArguments.h");
2603 if (ExtendedAttributeContains($callWith, "ActiveWindow")) {
2604 push(@callWithArgs, "activeDOMWindow(info.GetIsolate())");
2606 if (ExtendedAttributeContains($callWith, "FirstWindow")) {
2607 push(@callWithArgs, "firstDOMWindow(info.GetIsolate())");
2609 return ([@callWithArgs], $code);
2612 sub GenerateArgumentsCountCheck
2614 my $function = shift;
2615 my $interface = shift;
2616 my $hasExceptionState = shift;
2618 my $functionName = $function->name;
2619 my $interfaceName = $interface->name;
2620 my $implClassName = GetImplName($interface);
2622 my $isConstructor = $functionName eq "Constructor" || $functionName eq "NamedConstructor";
2623 my $numMandatoryParams = 0;
2624 my $allowNonOptional = 1;
2625 foreach my $param (@{$function->parameters}) {
2626 if ($param->isOptional or $param->isVariadic) {
2627 $allowNonOptional = 0;
2629 die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if !$allowNonOptional;
2630 $numMandatoryParams++;
2633 return "" unless $numMandatoryParams;
2635 my $argumentsCountCheckString = "";
2636 $argumentsCountCheckString .= " if (UNLIKELY(info.Length() < $numMandatoryParams)) {\n";
2637 if ($hasExceptionState) {
2638 $argumentsCountCheckString .= " exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments($numMandatoryParams, info.Length()));\n";
2639 $argumentsCountCheckString .= " exceptionState.throwIfNeeded();\n";
2640 } elsif ($isConstructor) {
2641 $argumentsCountCheckString .= " throwTypeError(ExceptionMessages::failedToConstruct(\"$interfaceName\", ExceptionMessages::notEnoughArguments($numMandatoryParams, info.Length())), info.GetIsolate());\n";
2643 $argumentsCountCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", ExceptionMessages::notEnoughArguments($numMandatoryParams, info.Length())), info.GetIsolate());\n";
2645 $argumentsCountCheckString .= " return;\n";
2646 $argumentsCountCheckString .= " }\n";
2647 return $argumentsCountCheckString;
2650 sub GenerateParametersCheck
2652 my $function = shift;
2653 my $interface = shift;
2654 my $forMainWorldSuffix = shift;
2655 my $hasExceptionState = shift;
2656 my $style = shift || "new";
2658 my $functionName = $function->name;
2659 my $interfaceName = $interface->name;
2660 my $implClassName = GetImplName($interface);
2662 my $parameterCheckString = "";
2664 my %replacements = ();
2666 foreach my $parameter (@{$function->parameters}) {
2667 my $humanFriendlyIndex = $paramIndex + 1;
2668 my $nativeType = GetNativeType($parameter->type, $parameter->extendedAttributes, "parameter");
2670 # Optional arguments without [Default=...] should generate an early call with fewer arguments.
2671 # Optional Dictionary arguments always considered to have default of empty dictionary.
2672 if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default"} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) {
2673 $parameterCheckString .= <<END;
2674 if (UNLIKELY(info.Length() <= $paramIndex)) {
2676 $parameterCheckString .= GenerateFunctionCallString($function, $paramIndex, " " x 2, $interface, $forMainWorldSuffix, $hasExceptionState, %replacements);
2677 $parameterCheckString .= <<END;
2683 my $parameterName = $parameter->name;
2684 if (IsCallbackInterface($parameter->type)) {
2685 my $v8ClassName = "V8" . $parameter->type;
2686 AddToImplIncludes("$v8ClassName.h");
2687 if ($parameter->isOptional) {
2688 $parameterCheckString .= " OwnPtr<" . $parameter->type . "> $parameterName;\n";
2689 $parameterCheckString .= " if (info.Length() > $paramIndex && !isUndefinedOrNull(info[$paramIndex])) {\n";
2690 $parameterCheckString .= " if (!info[$paramIndex]->IsFunction()) {\n";
2691 if ($hasExceptionState) {
2692 $parameterCheckString .= " exceptionState.throwTypeError(\"The callback provided as parameter $humanFriendlyIndex is not a function.\");\n";
2693 $parameterCheckString .= " exceptionState.throwIfNeeded();\n";
2695 $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"The callback provided as parameter $humanFriendlyIndex is not a function.\"), info.GetIsolate());\n";
2697 $parameterCheckString .= " return;\n";
2698 $parameterCheckString .= " }\n";
2699 $parameterCheckString .= " $parameterName = ${v8ClassName}::create(v8::Handle<v8::Function>::Cast(info[$paramIndex]), currentExecutionContext(info.GetIsolate()));\n";
2700 $parameterCheckString .= " }\n";
2702 $parameterCheckString .= " if (info.Length() <= $paramIndex || ";
2703 if ($parameter->isNullable) {
2704 $parameterCheckString .= "!(info[$paramIndex]->IsFunction() || info[$paramIndex]->IsNull())";
2706 $parameterCheckString .= "!info[$paramIndex]->IsFunction()";
2708 $parameterCheckString .= ") {\n";
2709 if ($hasExceptionState) {
2710 $parameterCheckString .= " exceptionState.throwTypeError(\"The callback provided as parameter $humanFriendlyIndex is not a function.\");\n";
2711 $parameterCheckString .= " exceptionState.throwIfNeeded();\n";
2713 $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"The callback provided as parameter $humanFriendlyIndex is not a function.\"), info.GetIsolate());\n";
2715 $parameterCheckString .= " return;\n";
2716 $parameterCheckString .= " }\n";
2717 $parameterCheckString .= " OwnPtr<" . $parameter->type . "> $parameterName = ";
2718 $parameterCheckString .= "info[$paramIndex]->IsNull() ? nullptr : " if $parameter->isNullable;
2719 $parameterCheckString .= "${v8ClassName}::create(v8::Handle<v8::Function>::Cast(info[$paramIndex]), currentExecutionContext(info.GetIsolate()));\n";
2721 } elsif ($parameter->extendedAttributes->{"Clamp"}) {
2722 my $nativeValue = "${parameterName}NativeValue";
2723 my $idlType = $parameter->type;
2724 $parameterCheckString .= " $nativeType $parameterName = 0;\n";
2725 $parameterCheckString .= " V8TRYCATCH_VOID(double, $nativeValue, info[$paramIndex]->NumberValue());\n";
2726 $parameterCheckString .= " if (!std::isnan($nativeValue))\n";
2727 $parameterCheckString .= " $parameterName = clampTo<$idlType>($nativeValue);\n";
2728 } elsif ($parameter->type eq "SerializedScriptValue") {
2729 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
2730 $parameterCheckString .= " $nativeType $parameterName = SerializedScriptValue::create(info[$paramIndex], 0, 0, exceptionState, info.GetIsolate());\n";
2731 $parameterCheckString .= " if (exceptionState.throwIfNeeded())\n";
2732 $parameterCheckString .= " return;\n";
2733 } elsif ($parameter->isVariadic) {
2734 my $nativeElementType = GetNativeType($parameter->type);
2735 if ($nativeElementType =~ />$/) {
2736 $nativeElementType .= " ";
2739 my $argType = $parameter->type;
2740 if (IsWrapperType($argType)) {
2741 $parameterCheckString .= " Vector<$nativeElementType> $parameterName;\n";
2742 $parameterCheckString .= " for (int i = $paramIndex; i < info.Length(); ++i) {\n";
2743 $parameterCheckString .= " if (!V8${argType}::hasInstance(info[i], info.GetIsolate())) {\n";
2744 if ($hasExceptionState) {
2745 $parameterCheckString .= " exceptionState.throwTypeError(\"parameter $humanFriendlyIndex is not of type \'$argType\'.\");\n";
2746 $parameterCheckString .= " exceptionState.throwIfNeeded();\n";
2748 $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $humanFriendlyIndex is not of type \'$argType\'.\"), info.GetIsolate());\n";
2750 $parameterCheckString .= " return;\n";
2751 $parameterCheckString .= " }\n";
2752 $parameterCheckString .= " $parameterName.append(V8${argType}::toNative(v8::Handle<v8::Object>::Cast(info[i])));\n";
2753 $parameterCheckString .= " }\n";
2755 $parameterCheckString .= " V8TRYCATCH_VOID(Vector<$nativeElementType>, $parameterName, toNativeArguments<$nativeElementType>(info, $paramIndex));\n";
2757 } elsif ($nativeType =~ /^V8StringResource/) {
2758 my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : "";
2759 my $jsValue = $parameter->isOptional && $default eq "NullString" ? "argumentOrNull(info, $paramIndex)" : "info[$paramIndex]";
2760 my $stringResourceParameterName = $parameterName;
2761 my $isNullable = IsNullableParameter($parameter);
2763 $parameterCheckString .= " bool ${parameterName}IsNull = $jsValue->IsNull();\n";
2764 $stringResourceParameterName .= "StringResource";
2766 $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $humanFriendlyIndex, $jsValue, $stringResourceParameterName, " ", "info.GetIsolate()");
2767 $parameterCheckString .= " String $parameterName = $stringResourceParameterName;\n" if $isNullable;
2768 if (IsEnumType($parameter->type)) {
2769 my @enumValues = ValidEnumValues($parameter->type);
2770 my @validEqualities = ();
2771 foreach my $enumValue (@enumValues) {
2772 push(@validEqualities, "string == \"$enumValue\"");
2774 my $enumValidationExpression = join(" || ", @validEqualities);
2775 $parameterCheckString .= " String string = $parameterName;\n";
2776 $parameterCheckString .= " if (!($enumValidationExpression)) {\n";
2777 if ($hasExceptionState) {
2778 $parameterCheckString .= " exceptionState.throwTypeError(\"parameter $humanFriendlyIndex (\'\" + string + \"\') is not a valid enum value.\");\n";
2779 $parameterCheckString .= " exceptionState.throwIfNeeded();\n";
2781 $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $humanFriendlyIndex (\'\" + string + \"\') is not a valid enum value.\"), info.GetIsolate());\n";
2783 $parameterCheckString .= " return;\n";
2784 $parameterCheckString .= " }\n";
2787 # If the [StrictTypeChecking] extended attribute is present, type
2788 # check interface type arguments for correct type and nullability.
2790 # If the argument is passed, and is not |undefined| or |null|, then
2791 # it must implement the interface type, otherwise throw a TypeError
2792 # If the parameter is nullable, then both |undefined| and |null|
2793 # pass a NULL pointer to the C++ code, otherwise these also throw.
2794 # Without [StrictTypeChecking], in all these cases NULL is silently
2795 # passed to the C++ code.
2797 # Per the Web IDL and ECMAScript specifications, incoming values
2798 # can always be converted to primitive types and strings (including
2799 # |undefined| and |null|), so do not throw TypeError for these.
2800 if ($function->extendedAttributes->{"StrictTypeChecking"} || $interface->extendedAttributes->{"StrictTypeChecking"}) {
2801 my $argValue = "info[$paramIndex]";
2802 my $argType = $parameter->type;
2803 if (IsWrapperType($argType)) {
2804 my $undefinedNullCheck = $parameter->isNullable ? " !isUndefinedOrNull($argValue) &&" : "";
2805 $parameterCheckString .= " if (info.Length() > $paramIndex &&$undefinedNullCheck !V8${argType}::hasInstance($argValue, info.GetIsolate())) {\n";
2806 if ($hasExceptionState) {
2807 $parameterCheckString .= " exceptionState.throwTypeError(\"parameter $humanFriendlyIndex is not of type \'$argType\'.\");\n";
2808 $parameterCheckString .= " exceptionState.throwIfNeeded();\n";
2810 $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $humanFriendlyIndex is not of type \'$argType\'.\"), info.GetIsolate());\n";
2812 $parameterCheckString .= " return;\n";
2813 $parameterCheckString .= " }\n";
2816 my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : "";
2817 my $jsValue = $parameter->isOptional && $default eq "NullString" ? "argumentOrNull(info, $paramIndex)" : "info[$paramIndex]";
2818 my $isNullable = IsNullableParameter($parameter);
2819 $parameterCheckString .= " bool ${parameterName}IsNull = $jsValue->IsNull();\n" if $isNullable;
2820 $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $humanFriendlyIndex, $jsValue, $parameterName, " ", "info.GetIsolate()");
2821 if ($nativeType eq 'Dictionary' or $nativeType eq 'ScriptPromise') {
2822 $parameterCheckString .= " if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject()) {\n";
2823 if ($hasExceptionState) {
2824 $parameterCheckString .= " exceptionState.throwTypeError(\"parameter ${humanFriendlyIndex} ('${parameterName}') is not an object.\");\n";
2825 $parameterCheckString .= " exceptionState.throwIfNeeded();\n";
2826 } elsif ($functionName eq "Constructor") {
2827 $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToConstruct(\"$interfaceName\", \"parameter ${humanFriendlyIndex} ('${parameterName}') is not an object.\"), info.GetIsolate());\n";
2829 $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter ${humanFriendlyIndex} ('${parameterName}') is not an object.\"), info.GetIsolate());\n";
2831 $parameterCheckString .= " return;\n";
2832 $parameterCheckString .= " }\n";
2838 return ($parameterCheckString, $paramIndex, %replacements);
2841 sub GenerateOverloadedConstructorCallback
2843 my $interface = shift;
2844 my $interfaceName = $interface->name;
2845 my $implClassName = GetImplName($interface);
2848 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info)
2851 my $leastNumMandatoryParams = 255;
2852 foreach my $constructor (@{$interface->constructors}) {
2853 my $name = "constructor" . $constructor->overloadedIndex;
2854 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($constructor);
2855 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
2856 $code .= " if ($parametersCheck) {\n";
2857 $code .= " ${implClassName}V8Internal::${name}(info);\n";
2858 $code .= " return;\n";
2861 if ($leastNumMandatoryParams >= 1) {
2863 ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());
2864 if (UNLIKELY(info.Length() < $leastNumMandatoryParams)) {
2865 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments($leastNumMandatoryParams, info.Length()));
2866 exceptionState.throwIfNeeded();
2869 exceptionState.throwTypeError(\"No matching constructor signature.\");
2870 exceptionState.throwIfNeeded();
2874 throwTypeError(ExceptionMessages::failedToConstruct(\"${interfaceName}\", \"No matching constructor signature.\"), info.GetIsolate());
2878 $implementation{nameSpaceInternal}->add($code);
2881 sub GenerateSingleConstructorCallback
2883 my $interface = shift;
2884 my $function = shift;
2886 my $interfaceName = $interface->name;
2887 my $implClassName = GetImplName($interface);
2888 my $v8ClassName = GetV8ClassName($interface);
2889 my $overloadedIndexString = "";
2890 if ($function->overloadedIndex > 0) {
2891 $overloadedIndexString .= $function->overloadedIndex;
2894 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesException"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor";
2895 my $hasExceptionState = $function->extendedAttributes->{"RaisesException"} || $constructorRaisesException || HasExceptionRaisingParameter($function);
2897 my @beforeArgumentList;
2898 my @afterArgumentList;
2901 static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v8::Value>& info)
2905 if ($hasExceptionState) {
2906 $code .= " ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
2908 if ($function->overloadedIndex == 0) {
2909 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionState);
2912 # FIXME: Currently [Constructor(...)] does not yet support optional arguments without [Default=...]
2913 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, "", $hasExceptionState);
2914 $code .= $parameterCheckString;
2916 if ($interface->extendedAttributes->{"ConstructorCallWith"}) {
2917 if (ExtendedAttributeContains($interface->extendedAttributes->{"ConstructorCallWith"}, "ExecutionContext")) {
2918 push(@beforeArgumentList, "context");
2919 $code .= " ExecutionContext* context = currentExecutionContext(info.GetIsolate());\n";
2921 if (ExtendedAttributeContains($interface->extendedAttributes->{"ConstructorCallWith"}, "Document")) {
2922 push(@beforeArgumentList, "document");
2923 $code .= " Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));\n";
2927 if ($constructorRaisesException) {
2928 push(@afterArgumentList, "exceptionState");
2933 foreach my $parameter (@{$function->parameters}) {
2934 last if $index eq $paramIndex;
2935 if ($replacements{$parameter->name}) {
2936 push(@argumentList, $replacements{$parameter->name});
2938 push(@argumentList, $parameter->name);
2943 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
2944 my $refPtrType = IsWillBeGarbageCollectedType($interfaceName) ? "RefPtrWillBeRawPtr<$implClassName>" : "RefPtr<$implClassName>";
2945 $code .= " $refPtrType impl = ${implClassName}::create(${argumentString});\n";
2946 $code .= " v8::Handle<v8::Object> wrapper = info.Holder();\n";
2948 if ($constructorRaisesException) {
2949 $code .= " if (exceptionState.throwIfNeeded())\n";
2950 $code .= " return;\n";
2955 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${v8ClassName}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
2956 v8SetReturnValue(info, wrapper);
2960 $implementation{nameSpaceInternal}->add($code);
2963 # The Web IDL specification states that Interface objects for interfaces MUST have a property named
2964 # "length" that returns the length of the shortest argument list of the entries in the effective
2965 # overload set for constructors. In other words, use the lowest number of mandatory arguments among
2967 sub GetInterfaceLength
2969 my $interface = shift;
2971 my $leastConstructorLength = 0;
2972 if ($interface->extendedAttributes->{"EventConstructor"}) {
2973 $leastConstructorLength = 1;
2974 } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"CustomConstructor"}) {
2975 my @constructors = @{$interface->constructors};
2976 my @customConstructors = @{$interface->customConstructors};
2977 $leastConstructorLength = 255;
2978 foreach my $constructor (@constructors, @customConstructors) {
2979 my $constructorLength = GetFunctionLength($constructor);
2980 $leastConstructorLength = $constructorLength if ($constructorLength < $leastConstructorLength);
2984 return $leastConstructorLength;
2987 sub GenerateConstructorCallback
2989 my $interface = shift;
2991 my $implClassName = GetImplName($interface);
2992 my $v8ClassName = GetV8ClassName($interface);
2994 $code .= "void ${v8ClassName}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)\n";
2996 $code .= " TRACE_EVENT_SCOPED_SAMPLING_STATE(\"Blink\", \"DOMConstructor\");\n";
2997 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"MeasureAs"});
2998 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"DeprecateAs"});
2999 $code .= GenerateConstructorHeader($interface->name);
3000 if (HasCustomConstructor($interface)) {
3001 $code .= " ${v8ClassName}::constructorCustom(info);\n";
3003 $code .= " ${implClassName}V8Internal::constructor(info);\n";
3006 $implementation{nameSpaceWebCore}->add($code);
3009 sub GenerateConstructor
3011 my $interface = shift;
3013 if (@{$interface->constructors} == 1) {
3014 GenerateSingleConstructorCallback($interface, @{$interface->constructors}[0]);
3016 foreach my $constructor (@{$interface->constructors}) {
3017 GenerateSingleConstructorCallback($interface, $constructor);
3019 GenerateOverloadedConstructorCallback($interface);
3023 sub GenerateEventConstructor
3025 my $interface = shift;
3027 my $interfaceName = $interface->name;
3028 my $implClassName = GetImplName($interface);
3029 my $v8ClassName = GetV8ClassName($interface);
3031 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesException"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor";
3033 my @anyAttributeNames;
3034 foreach my $attribute (@{$interface->attributes}) {
3035 if ($attribute->type eq "any") {
3036 push(@anyAttributeNames, $attribute->name);
3040 AddToImplIncludes("bindings/v8/Dictionary.h");
3041 $implementation{nameSpaceInternal}->add(<<END);
3042 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info)
3044 ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());
3045 if (info.Length() < 1) {
3046 exceptionState.throwTypeError("An event name must be provided.");
3047 exceptionState.throwIfNeeded();
3051 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]);
3054 foreach my $attrName (@anyAttributeNames) {
3055 $implementation{nameSpaceInternal}->add(" v8::Local<v8::Value> ${attrName};\n");
3058 $implementation{nameSpaceInternal}->add(<<END);
3059 ${implClassName}Init eventInit;
3060 if (info.Length() >= 2) {
3061 V8TRYCATCH_VOID(Dictionary, options, Dictionary(info[1], info.GetIsolate()));
3062 if (!initialize${implClassName}(eventInit, options, exceptionState, info)) {
3063 exceptionState.throwIfNeeded();
3068 # Store 'any'-typed properties on the wrapper to avoid leaking them between isolated worlds.
3069 foreach my $attrName (@anyAttributeNames) {
3070 $implementation{nameSpaceInternal}->add(<<END);
3071 options.get("${attrName}", ${attrName});
3072 if (!${attrName}.IsEmpty())
3073 setHiddenValue(info.GetIsolate(), info.Holder(), "${attrName}", ${attrName});
3077 $implementation{nameSpaceInternal}->add(<<END);
3081 my $exceptionStateArgument = "";
3082 if ($constructorRaisesException) {
3083 ${exceptionStateArgument} = ", exceptionState";
3086 $implementation{nameSpaceInternal}->add(<<END);
3087 RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit${exceptionStateArgument});
3090 if ($constructorRaisesException) {
3091 $implementation{nameSpaceInternal}->add(<<END);
3092 if (exceptionState.throwIfNeeded())
3097 if (@anyAttributeNames) {
3098 # Separate check to simplify Python code
3099 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
3101 if (@anyAttributeNames && $interface->name ne 'ErrorEvent') {
3102 # If we're in an isolated world, create a SerializedScriptValue and
3103 # store it in the event for later cloning if the property is accessed
3104 # from another world.
3105 # The main world case is handled lazily (in Custom code).
3107 # We do not clone Error objects (exceptions), for 2 reasons:
3108 # 1) Errors carry a reference to the isolated world's global object,
3109 # and thus passing it around would cause leakage.
3110 # 2) Errors cannot be cloned (or serialized):
3111 # http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data
3112 $implementation{nameSpaceInternal}->add(" if (DOMWrapperWorld::current(info.GetIsolate())->isIsolatedWorld()) {\n");
3113 foreach my $attrName (@anyAttributeNames) {
3114 my $setter = "setSerialized" . FirstLetterToUpperCase($attrName);
3115 $implementation{nameSpaceInternal}->add(<<END);
3116 if (!${attrName}.IsEmpty())
3117 event->${setter}(SerializedScriptValue::createAndSwallowExceptions(${attrName}, info.GetIsolate()));
3120 $implementation{nameSpaceInternal}->add(" }\n\n");
3123 $implementation{nameSpaceInternal}->add(<<END);
3124 v8::Handle<v8::Object> wrapper = info.Holder();
3125 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(event.release(), &${v8ClassName}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
3126 v8SetReturnValue(info, wrapper);
3133 bool initialize${implClassName}(${implClassName}Init& eventInit, const Dictionary& options, ExceptionState& exceptionState, const v8::FunctionCallbackInfo<v8::Value>& info, const String& forEventName)
3135 Dictionary::ConversionContext conversionContext(forEventName.isEmpty() ? String("${interfaceName}") : forEventName, "", exceptionState);
3138 if ($interface->parent) {
3139 my $interfaceBase = $interface->parent;
3141 if (!initialize${interfaceBase}(eventInit, options, exceptionState, info, forEventName.isEmpty() ? String("${interfaceName}") : forEventName))
3147 foreach my $attribute (@{$interface->attributes}) {
3148 if ($attribute->extendedAttributes->{"InitializedByEventConstructor"}) {
3149 if ($attribute->type ne "any") {
3150 my $attributeName = $attribute->name;
3151 my $attributeImplName = GetImplName($attribute);
3153 my $isNullable = $attribute->isNullable ? "true" : "false";
3154 my $dictionaryGetter = "options.convert(conversionContext.setConversionType(\"" . $attribute->type . "\", $isNullable), \"$attributeName\", eventInit.$attributeImplName)";
3155 my $deprecation = $attribute->extendedAttributes->{"DeprecateAs"};
3157 $code .= " if ($dictionaryGetter) {\n";
3158 $code .= " if (options.hasProperty(\"$attributeName\"))\n";
3159 $code .= " " . GenerateDeprecationNotification($deprecation);
3160 $code .= " } else {\n";
3161 $code .= " return false;\n";
3164 $code .= " if (!$dictionaryGetter)\n";
3165 $code .= " return false;\n";
3176 $implementation{nameSpaceWebCore}->add($code);
3179 sub GenerateNamedConstructor
3181 my $function = shift;
3182 my $interface = shift;
3184 my $interfaceName = $interface->name;
3185 my $implClassName = GetImplName($interface);
3186 my $v8ClassName = GetV8ClassName($interface);
3187 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesException"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor";
3188 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"} || $constructorRaisesException || HasExceptionRaisingParameter($function);
3190 my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"});
3191 my $maybeDeprecateFeature = GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"});
3193 my @beforeArgumentList;
3194 my @afterArgumentList;
3196 my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObject") ? "${v8ClassName}::toActiveDOMObject" : "0";
3197 my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8ClassName}::toEventTarget" : "0";
3198 my $derefObject = "${v8ClassName}::derefObject";
3200 $implementation{nameSpaceWebCore}->add(<<END);
3201 const WrapperTypeInfo ${v8ClassName}Constructor::wrapperTypeInfo = { gin::kEmbedderBlink, ${v8ClassName}Constructor::domTemplate, $derefObject, $toActiveDOMObject, $toEventTarget, 0, ${v8ClassName}::installPerContextEnabledMethods, 0, WrapperTypeObjectPrototype, false };
3207 static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
3210 $code .= $maybeObserveFeature if $maybeObserveFeature;
3211 $code .= $maybeDeprecateFeature if $maybeDeprecateFeature;
3212 $code .= GenerateConstructorHeader($function->extendedAttributes->{"NamedConstructor"});
3214 Document* document = currentDocument(info.GetIsolate());
3217 // Make sure the document is added to the DOM Node map. Otherwise, the ${implClassName} instance
3218 // may end up being the only node in the map and get garbage-collected prematurely.
3219 toV8(document, info.Holder(), info.GetIsolate());
3223 my $hasExceptionState = $raisesExceptions;
3224 if ($hasExceptionState) {
3225 $code .= " ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
3227 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionState);
3229 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, "", $hasExceptionState);
3230 $code .= $parameterCheckString;
3232 push(@beforeArgumentList, "*document");
3234 if ($constructorRaisesException) {
3235 push(@afterArgumentList, "exceptionState");
3240 foreach my $parameter (@{$function->parameters}) {
3241 last if $index eq $paramIndex;
3242 if ($replacements{$parameter->name}) {
3243 push(@argumentList, $replacements{$parameter->name});
3245 push(@argumentList, $parameter->name);
3250 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
3251 $code .= " RefPtr<${implClassName}> impl = ${implClassName}::createForJSConstructor(${argumentString});\n";
3252 $code .= " v8::Handle<v8::Object> wrapper = info.Holder();\n";
3254 if ($constructorRaisesException) {
3255 $code .= " if (exceptionState.throwIfNeeded())\n";
3256 $code .= " return;\n";
3261 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${v8ClassName}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
3262 v8SetReturnValue(info, wrapper);
3266 $implementation{nameSpaceWebCore}->add($code);
3269 v8::Handle<v8::FunctionTemplate> ${v8ClassName}Constructor::domTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType)
3271 // This is only for getting a unique pointer which we can pass to privateTemplate.
3272 static int privateTemplateUniqueKey;
3273 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
3274 v8::Local<v8::FunctionTemplate> result = data->privateTemplateIfExists(currentWorldType, &privateTemplateUniqueKey);
3275 if (!result.IsEmpty())
3278 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
3279 v8::EscapableHandleScope scope(isolate);
3280 result = v8::FunctionTemplate::New(isolate, ${v8ClassName}ConstructorCallback);
3282 v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate();
3283 instanceTemplate->SetInternalFieldCount(${v8ClassName}::internalFieldCount);
3284 result->SetClassName(v8AtomicString(isolate, "${implClassName}"));
3285 result->Inherit(${v8ClassName}::domTemplate(isolate, currentWorldType));
3286 data->setPrivateTemplate(currentWorldType, &privateTemplateUniqueKey, result);
3288 return scope.Escape(result);
3292 $implementation{nameSpaceWebCore}->add($code);
3295 sub GenerateConstructorHeader
3297 my $constructorName = shift;
3299 AddToImplIncludes("bindings/v8/V8ObjectConstructor.h");
3300 my $content = <<END;
3301 if (!info.IsConstructCall()) {
3302 throwTypeError(ExceptionMessages::failedToConstruct("$constructorName", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate());
3306 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
3307 v8SetReturnValue(info, info.Holder());
3315 sub GenerateAttributeConfigurationArray
3317 my $interface = shift;
3318 my $attributes = shift;
3319 my $exposeJSAccessors = shift;
3322 foreach my $attribute (@$attributes) {
3323 my $conditionalString = GenerateConditionalString($attribute);
3325 $subCode .= "#if ${conditionalString}\n" if $conditionalString;
3326 $subCode .= GenerateAttributeConfiguration($interface, $attribute, ",", "", $exposeJSAccessors);
3327 $subCode .= "#endif // ${conditionalString}\n" if $conditionalString;
3333 sub GenerateAttributeConfigurationParameters
3335 my $interface = shift;
3336 my $attribute = shift;
3337 my $attrName = $attribute->name;
3338 my $attrExt = $attribute->extendedAttributes;
3339 my $implClassName = GetImplName($interface);
3341 my @accessControlList;
3342 if (my $doNotCheckSecurity = $attrExt->{"DoNotCheckSecurity"}) {
3343 if ($doNotCheckSecurity eq "Getter") {
3344 push(@accessControlList, "v8::ALL_CAN_READ");
3345 } elsif ($doNotCheckSecurity eq "Setter") {
3346 push(@accessControlList, "v8::ALL_CAN_WRITE");
3348 push(@accessControlList, "v8::ALL_CAN_READ");
3349 if (!IsReadonly($attribute)) {
3350 push(@accessControlList, "v8::ALL_CAN_WRITE");
3354 if ($attrExt->{"Unforgeable"}) {
3355 push(@accessControlList, "v8::PROHIBITS_OVERWRITING");
3357 @accessControlList = ("v8::DEFAULT") unless @accessControlList;
3358 my $accessControl = "static_cast<v8::AccessControl>(" . join(" | ", @accessControlList) . ")";
3360 my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attribute) || "";
3361 if ($customAccessor eq "VALUE_IS_MISSING") {
3362 # use the naming convension, interface + (capitalize) attr name
3363 $customAccessor = $implClassName . "::" . $attrName;
3368 my $getterForMainWorld;
3369 my $setterForMainWorld;
3371 my $isConstructor = ($attribute->type =~ /Constructor$/);
3374 # As per Web IDL specification, constructor properties on the ECMAScript global object should be
3375 # configurable and should not be enumerable.
3376 my @propAttributeList;
3377 if ($attrExt->{"NotEnumerable"} || $isConstructor) {
3378 push(@propAttributeList, "v8::DontEnum");
3380 if ($attrExt->{"Unforgeable"} && !$isConstructor) {
3381 push(@propAttributeList, "v8::DontDelete");
3383 @propAttributeList = ("v8::None") unless @propAttributeList;
3384 my $propAttribute = join(" | ", @propAttributeList);
3386 my $onProto = "0 /* on instance */";
3387 my $data = "0"; # no data
3390 if ($isConstructor) {
3391 my $constructorType = $attribute->type;
3392 $constructorType =~ s/Constructor$//;
3394 # For NamedConstructors we do not generate a header file. The code for the NamedConstructor
3395 # gets generated when we generate the code for its interface.
3396 if ($constructorType !~ /Constructor$/) {
3397 AddToImplIncludes("V8${constructorType}.h");
3399 $data = "const_cast<WrapperTypeInfo*>(&V8${constructorType}::wrapperTypeInfo)";
3400 $getter = "${implClassName}V8Internal::${implClassName}ConstructorGetter";
3401 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttributeSetterCallback";
3402 $getterForMainWorld = "0";
3403 $setterForMainWorld = "0";
3405 # Default Getter and Setter
3406 $getter = "${implClassName}V8Internal::${attrName}AttributeGetterCallback";
3407 $setter = "${implClassName}V8Internal::${attrName}AttributeSetterCallback";
3408 $getterForMainWorld = "${getter}ForMainWorld";
3409 $setterForMainWorld = "${setter}ForMainWorld";
3411 if (!HasCustomSetter($attribute) && !$attrExt->{"PutForwards"} && $attrExt->{"Replaceable"}) {
3412 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttributeSetterCallback";
3413 $setterForMainWorld = "0";
3417 # Read only attributes
3418 if (IsReadonly($attribute)) {
3420 $setterForMainWorld = "0";
3423 # An accessor can be installed on the prototype
3424 if ($attrExt->{"OnPrototype"}) {
3425 $onProto = "1 /* on prototype */";
3428 if (!$attrExt->{"PerWorldBindings"}) {
3429 $getterForMainWorld = "0";
3430 $setterForMainWorld = "0";
3433 return ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, "static_cast<v8::PropertyAttribute>($propAttribute)", $onProto);
3436 sub GenerateAttributeConfiguration
3438 my $interface = shift;
3439 my $attribute = shift;
3440 my $delimiter = shift;
3442 my $exposeJSAccessors = shift;
3446 my ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, $propAttribute, $onProto) = GenerateAttributeConfigurationParameters($interface, $attribute, $exposeJSAccessors);
3447 if ($exposeJSAccessors) {
3448 $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, $propAttribute}" . $delimiter . "\n";
3450 $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, $propAttribute, $onProto}" . $delimiter . "\n";
3455 sub GenerateStaticAttribute
3457 my $interface = shift;
3458 my $attribute = shift;
3459 my $attrExt = $attribute->extendedAttributes;
3462 my ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, $propAttribute, $onProto) = GenerateAttributeConfigurationParameters($interface, $attribute);
3464 die "Static attributes do not support optimized getters or setters for the main world" if $getterForMainWorld || $setterForMainWorld;
3466 my $conditionalString = GenerateConditionalString($attribute);
3468 $code .= "#if ${conditionalString}\n" if $conditionalString;
3469 $code .= " functionTemplate->SetNativeDataProperty(v8AtomicString(isolate, \"$attrName\"), $getter, $setter, v8::External::New(isolate, $data), $propAttribute, v8::Handle<v8::AccessorSignature>(), $accessControl);\n";
3470 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
3475 sub IsStandardFunction
3477 my $interface = shift;
3478 my $function = shift;
3480 my $interfaceName = $interface->name;
3481 my $attrExt = $function->extendedAttributes;
3482 return 0 if $attrExt->{"Unforgeable"};
3483 return 0 if $function->isStatic;
3484 return 0 if $attrExt->{"RuntimeEnabled"};
3485 return 0 if $attrExt->{"PerContextEnabled"};
3486 return 0 if $attrExt->{"DoNotCheckSignature"};
3487 return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "Window"));
3488 return 0 if $attrExt->{"NotEnumerable"};
3489 return 0 if $attrExt->{"ReadOnly"};
3493 sub GenerateNonStandardFunction
3495 my $interface = shift;
3496 my $function = shift;
3499 my $implClassName = GetImplName($interface);
3500 my $attrExt = $function->extendedAttributes;
3501 my $name = $function->name;
3503 my $property_attributes = "v8::DontDelete";
3504 if ($attrExt->{"NotEnumerable"}) {
3505 $property_attributes .= " | v8::DontEnum";
3507 if ($attrExt->{"ReadOnly"}) {
3508 $property_attributes .= " | v8::ReadOnly";
3511 my $commentInfo = "Function '$name' (Extended Attributes: '" . join(' ', keys(%{$attrExt})) . "')";
3513 my $template = "prototypeTemplate";
3514 if ($attrExt->{"Unforgeable"}) {
3515 $template = "instanceTemplate";
3517 if ($function->isStatic) {
3518 $template = "functionTemplate";
3521 my $conditional4 = ""; # 4 space indent context
3522 my $conditional8 = ""; # 8 space indent context
3523 if ($attrExt->{"RuntimeEnabled"}) {
3524 # Only call Set()/SetAccessor() if this method should be enabled
3525 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($function);
3526 $conditional4 = "if (${runtimeEnabledFunction}())\n ";
3528 if ($attrExt->{"PerContextEnabled"}) {
3529 # Only call Set()/SetAccessor() if this method should be enabled
3530 my $contextEnabledFunction = GetContextEnabledFunctionName($function);
3531 $conditional4 = "if (${contextEnabledFunction}(impl->document()))\n ";
3533 $conditional8 = $conditional4 . " " if $conditional4 ne "";
3535 if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCheckSecurity"}) {
3536 my $setter = $attrExt->{"ReadOnly"} ? "0" : "${implClassName}V8Internal::${implClassName}OriginSafeMethodSetterCallback";
3537 # Functions that are marked DoNotCheckSecurity are always readable but if they are changed
3538 # and then accessed on a different domain we do not return the underlying value but instead
3539 # return a new copy of the original function. This is achieved by storing the changed value
3540 # as hidden property.
3541 if ($function->extendedAttributes->{"PerWorldBindings"}) {
3543 if (currentWorldType == MainWorld) {
3544 ${conditional8}$template->SetAccessor(v8AtomicString(isolate, "$name"), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCallbackForMainWorld, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
3546 ${conditional8}$template->SetAccessor(v8AtomicString(isolate, "$name"), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCallback, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));
3550 $code .= " ${conditional4}$template->SetAccessor(v8AtomicString(isolate, \"$name\"), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCallback, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));\n";
3556 my $signature = "defaultSignature";
3557 if ($attrExt->{"DoNotCheckSignature"} || $function->isStatic) {
3558 $signature = "v8::Local<v8::Signature>()";
3561 my $conditionalString = GenerateConditionalString($function);
3562 $code .= "#if ${conditionalString}\n" if $conditionalString;
3564 if ($property_attributes eq "v8::DontDelete") {
3565 $property_attributes = "";
3567 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)";
3570 if ($template eq "prototypeTemplate" && $conditional4 eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
3571 die "This shouldn't happen: Class '$implClassName' $commentInfo\n";
3574 my $functionLength = GetFunctionLength($function);
3576 if ($function->extendedAttributes->{"PerWorldBindings"}) {
3577 $code .= " if (currentWorldType == MainWorld) {\n";
3578 $code .= " ${conditional8}$template->Set(v8AtomicString(isolate, \"$name\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}MethodCallbackForMainWorld, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n";
3579 $code .= " } else {\n";
3580 $code .= " ${conditional8}$template->Set(v8AtomicString(isolate, \"$name\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n";
3583 $code .= " ${conditional4}$template->Set(v8AtomicString(isolate, \"$name\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n";
3585 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
3589 sub GenerateIsNullExpression
3592 my $variableName = shift;
3593 if (IsUnionType($type)) {
3594 my $types = $type->unionMemberTypes;
3595 my @expression = ();
3596 for my $i (0 .. scalar(@$types)-1) {
3597 my $unionMemberEnabledVariable = $variableName . $i . "Enabled";
3598 push @expression, "!${unionMemberEnabledVariable}";
3600 return join " && ", @expression;
3602 if (IsRefPtrType($type)) {
3603 return "!${variableName}";
3604 } elsif ($type eq "DOMString") {
3605 return "${variableName}.isNull()";
3606 } elsif ($type eq "Promise") {
3607 return "${variableName}.isNull()";
3613 sub GenerateIfElseStatement
3616 my $outputVariableName = shift;
3617 my $conditions = shift;
3618 my $statements = shift;
3621 if (@$conditions == 1) {
3622 $code .= " ${type} ${outputVariableName} = " . $statements->[0] . "\n";
3624 $code .= " ${type} ${outputVariableName};\n";
3625 for my $i (0 .. @$conditions - 1) {
3626 my $token = "else if";
3627 $token = "if" if $i == 0;
3628 $token = "else" if $i == @$conditions - 1;
3629 $code .= " ${token}";
3630 $code .= " (" . $conditions->[$i] . ")" if $conditions->[$i];
3632 $code .= " ${outputVariableName} = " . $statements->[$i] . "\n";
3638 sub GenerateImplementationIndexedPropertyAccessors
3640 my $interface = shift;
3641 my $interfaceName = $interface->name;
3642 my $implClassName = GetImplName($interface);
3643 my $v8ClassName = GetV8ClassName($interface);
3645 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
3646 if ($indexedGetterFunction) {
3647 # includes for return type even if custom
3648 my $returnType = $indexedGetterFunction->type;
3649 AddIncludesForType($returnType);
3650 my $hasCustomIndexedGetter = $indexedGetterFunction->extendedAttributes->{"Custom"};
3651 if (!$hasCustomIndexedGetter) {
3652 GenerateImplementationIndexedPropertyGetter($interface, $indexedGetterFunction);
3654 GenerateImplementationIndexedPropertyGetterCallback($interface, $hasCustomIndexedGetter);
3657 my $indexedSetterFunction = GetIndexedSetterFunction($interface);
3658 if ($indexedSetterFunction) {
3659 AddIncludesForType($indexedSetterFunction->parameters->[1]->type); # includes for argument type even if custom
3660 my $hasCustomIndexedSetter = $indexedSetterFunction->extendedAttributes->{"Custom"};
3661 if (!$hasCustomIndexedSetter) {
3662 GenerateImplementationIndexedPropertySetter($interface, $indexedSetterFunction);
3664 GenerateImplementationIndexedPropertySetterCallback($interface, $hasCustomIndexedSetter);
3667 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface);
3668 if ($indexedDeleterFunction) {
3669 my $hasCustomIndexedDeleter = $indexedDeleterFunction->extendedAttributes->{"Custom"};
3670 if (!$hasCustomIndexedDeleter) {
3671 GenerateImplementationIndexedPropertyDeleter($interface, $indexedDeleterFunction);
3673 GenerateImplementationIndexedPropertyDeleterCallback($interface, $hasCustomIndexedDeleter);
3676 my $indexedEnumeratorFunction = $indexedGetterFunction;
3677 $indexedEnumeratorFunction = 0 if $indexedGetterFunction && $indexedGetterFunction->extendedAttributes->{"NotEnumerable"};
3679 my $indexedQueryFunction = 0;
3680 # If there is an enumerator, there MUST be a query method to properly communicate property attributes.
3681 my $hasQuery = $indexedQueryFunction || $indexedEnumeratorFunction;
3683 my $setOn = "Instance";
3685 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on Window
3686 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
3687 # get implementation straight out of the Window prototype regardless of what prototype is actually set
3689 if ($interfaceName eq "Window") {
3690 $setOn = "Prototype";
3694 if ($indexedGetterFunction || $indexedSetterFunction || $indexedDeleterFunction || $indexedEnumeratorFunction || $hasQuery) {
3695 $code .= " functionTemplate->${setOn}Template()->SetIndexedPropertyHandler(${implClassName}V8Internal::indexedPropertyGetterCallback";
3696 $code .= $indexedSetterFunction ? ", ${implClassName}V8Internal::indexedPropertySetterCallback" : ", 0";
3697 $code .= ", 0"; # IndexedPropertyQuery -- not being used at the moment.
3698 $code .= $indexedDeleterFunction ? ", ${implClassName}V8Internal::indexedPropertyDeleterCallback" : ", 0";
3699 $code .= $indexedEnumeratorFunction ? ", indexedPropertyEnumerator<${implClassName}>" : ", 0";
3706 sub GenerateImplementationIndexedPropertyGetter
3708 my $interface = shift;
3709 my $indexedGetterFunction = shift;
3710 my $implClassName = GetImplName($interface);
3711 my $v8ClassName = GetV8ClassName($interface);
3712 my $methodName = GetImplName($indexedGetterFunction) || "anonymousIndexedGetter";
3714 my $returnType = $indexedGetterFunction->type;
3715 my $nativeType = GetNativeType($returnType);
3716 my $nativeValue = "result";
3717 $nativeValue .= ".release()" if (IsRefPtrType($returnType));
3718 my $isNull = GenerateIsNullExpression($returnType, "result");
3719 my $returnJSValueCode = NativeToJSValue($indexedGetterFunction->type, $indexedGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.GetIsolate()", "info", "imp", "", "return");
3720 my $raisesExceptions = $indexedGetterFunction->extendedAttributes->{"RaisesException"};
3721 my $methodCallCode = GenerateMethodCall($returnType, "result", "imp->${methodName}", "index", $raisesExceptions);
3722 my $getterCode = "static void indexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3723 $getterCode .= "{\n";
3724 $getterCode .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());\n";
3725 if ($raisesExceptions) {
3726 $getterCode .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n";
3728 $getterCode .= $methodCallCode . "\n";
3729 if ($raisesExceptions) {
3730 $getterCode .= " if (exceptionState.throwIfNeeded())\n";
3731 $getterCode .= " return;\n";
3733 if (IsUnionType($returnType)) {
3734 $getterCode .= "${returnJSValueCode}\n";
3735 $getterCode .= " return;\n";
3737 $getterCode .= " if (${isNull})\n";
3738 $getterCode .= " return;\n";
3739 $getterCode .= $returnJSValueCode . "\n";
3741 $getterCode .= "}\n\n";
3742 $implementation{nameSpaceInternal}->add($getterCode);
3745 sub GenerateImplementationIndexedPropertyGetterCallback
3747 my $interface = shift;
3748 my $hasCustom = shift;
3749 my $implClassName = GetImplName($interface);
3750 my $v8ClassName = GetV8ClassName($interface);
3752 my $code = "static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3754 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n";
3756 $code .= " ${v8ClassName}::indexedPropertyGetterCustom(index, info);\n";
3758 $code .= " ${implClassName}V8Internal::indexedPropertyGetter(index, info);\n";
3760 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3762 $implementation{nameSpaceInternal}->add($code);
3765 sub GenerateImplementationIndexedPropertySetterCallback
3767 my $interface = shift;
3768 my $hasCustom = shift;
3769 my $implClassName = GetImplName($interface);
3770 my $v8ClassName = GetV8ClassName($interface);
3772 my $code = "static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3774 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n";
3776 $code .= " ${v8ClassName}::indexedPropertySetterCustom(index, jsValue, info);\n";
3778 $code .= " ${implClassName}V8Internal::indexedPropertySetter(index, jsValue, info);\n";
3780 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3782 $implementation{nameSpaceInternal}->add($code);
3785 sub GenerateImplementationIndexedPropertyDeleterCallback
3787 my $interface = shift;
3788 my $hasCustom = shift;
3789 my $implClassName = GetImplName($interface);
3790 my $v8ClassName = GetV8ClassName($interface);
3792 my $code = "static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
3794 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n";
3796 $code .= " ${v8ClassName}::indexedPropertyDeleterCustom(index, info);\n";
3798 $code .= " ${implClassName}V8Internal::indexedPropertyDeleter(index, info);\n";
3800 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3802 $implementation{nameSpaceInternal}->add($code);
3805 sub GenerateImplementationIndexedPropertySetter
3807 my $interface = shift;
3808 my $indexedSetterFunction = shift;
3809 my $implClassName = GetImplName($interface);
3810 my $v8ClassName = GetV8ClassName($interface);
3811 my $methodName = GetImplName($indexedSetterFunction) || "anonymousIndexedSetter";
3812 my $interfaceName = $interface->name;
3814 my $type = $indexedSetterFunction->parameters->[1]->type;
3815 my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesException"};
3816 my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttributes->{"TreatNullAs"};
3817 my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttributes->{"TreatUndefinedAs"};
3819 my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3822 my $asSetterValue = 0;
3823 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());\n";
3824 $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->type, $indexedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "propertyValue", " ", "info.GetIsolate()");
3826 my $extraArguments = "";
3827 if ($raisesExceptions || IsIntegerType($type)) {
3828 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n";
3829 if ($raisesExceptions) {
3830 $extraArguments = ", exceptionState";
3834 if ($indexedSetterFunction->extendedAttributes->{"StrictTypeChecking"} && IsWrapperType($type)) {
3836 if (!isUndefinedOrNull(jsValue) && !V8${type}::hasInstance(jsValue, info.GetIsolate())) {
3837 exceptionState.throwTypeError("The provided value is not of type '$type'.");
3838 exceptionState.throwIfNeeded();
3844 $code .= " bool result = imp->${methodName}(index, propertyValue$extraArguments);\n";
3846 if ($raisesExceptions) {
3847 $code .= " if (exceptionState.throwIfNeeded())\n";
3848 $code .= " return;\n";
3850 $code .= " if (!result)\n";
3851 $code .= " return;\n";
3852 $code .= " v8SetReturnValue(info, jsValue);\n";
3854 $implementation{nameSpaceInternal}->add($code);
3857 sub GenerateImplementationNamedPropertyAccessors
3859 my $interface = shift;
3861 my $interfaceName = $interface->name;
3862 my $implClassName = GetImplName($interface);
3863 my $v8ClassName = GetV8ClassName($interface);
3865 my $namedGetterFunction = GetNamedGetterFunction($interface);
3866 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction->extendedAttributes->{"NotEnumerable"};
3868 if ($namedGetterFunction) {
3869 # includes for return type even if custom
3870 my $returnType = $namedGetterFunction->type;
3871 AddIncludesForType($returnType);
3872 my $hasCustomNamedGetter = HasCustomPropertyGetter($namedGetterFunction->extendedAttributes);
3873 if (!$hasCustomNamedGetter) {
3874 GenerateImplementationNamedPropertyGetter($interface, $namedGetterFunction);
3876 GenerateImplementationNamedPropertyGetterCallback($interface, $hasCustomNamedGetter);
3879 my $namedSetterFunction = GetNamedSetterFunction($interface);
3880 if ($namedSetterFunction) {
3881 AddIncludesForType($namedSetterFunction->parameters->[1]->type); # includes for argument type even if custom
3882 my $hasCustomNamedSetter = $namedSetterFunction->extendedAttributes->{"Custom"};
3883 if (!$hasCustomNamedSetter) {
3884 GenerateImplementationNamedPropertySetter($interface, $namedSetterFunction);
3886 GenerateImplementationNamedPropertySetterCallback($interface, $hasCustomNamedSetter);
3889 if ($namedEnumeratorFunction) {
3890 my $hasCustomNamedQuery = ExtendedAttributeContains($namedGetterFunction->extendedAttributes->{"Custom"}, "PropertyQuery");
3891 if (!$hasCustomNamedQuery) {
3892 GenerateImplementationNamedPropertyQuery($interface);
3894 GenerateImplementationNamedPropertyQueryCallback($interface, $hasCustomNamedQuery);
3897 my $namedDeleterFunction = GetNamedDeleterFunction($interface);
3898 if ($namedDeleterFunction) {
3899 my $hasCustomNamedDeleter = $namedDeleterFunction->extendedAttributes->{"Custom"};
3900 if (!$hasCustomNamedDeleter) {
3901 GenerateImplementationNamedPropertyDeleter($interface, $namedDeleterFunction);
3903 GenerateImplementationNamedPropertyDeleterCallback($interface, $hasCustomNamedDeleter);
3906 if ($namedEnumeratorFunction) {
3907 my $hasCustomNamedEnumerator = ExtendedAttributeContains($namedGetterFunction->extendedAttributes->{"Custom"}, "PropertyEnumerator");
3908 if (!$hasCustomNamedEnumerator) {
3909 GenerateImplementationNamedPropertyEnumerator($interface);
3911 GenerateImplementationNamedPropertyEnumeratorCallback($interface, $hasCustomNamedEnumerator);
3915 if ($namedGetterFunction || $namedSetterFunction || $namedDeleterFunction || $namedEnumeratorFunction) {
3916 my $setOn = "Instance";
3918 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on Window
3919 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
3920 # get implementation straight out of the Window prototype regardless of what prototype is actually set
3922 if ($interfaceName eq "Window") {
3923 $setOn = "Prototype";
3926 $subCode .= " functionTemplate->${setOn}Template()->SetNamedPropertyHandler(";
3927 $subCode .= $namedGetterFunction ? "${implClassName}V8Internal::namedPropertyGetterCallback, " : "0, ";
3928 $subCode .= $namedSetterFunction ? "${implClassName}V8Internal::namedPropertySetterCallback, " : "0, ";
3929 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::namedPropertyQueryCallback, " : "0, ";
3930 $subCode .= $namedDeleterFunction ? "${implClassName}V8Internal::namedPropertyDeleterCallback, " : "0, ";
3931 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::namedPropertyEnumeratorCallback" : "0";
3938 sub GenerateImplementationNamedPropertyGetterCallback
3940 my $interface = shift;
3941 my $hasCustom = shift;
3942 my $implClassName = GetImplName($interface);
3943 my $v8ClassName = GetV8ClassName($interface);
3945 my $code = "static void namedPropertyGetterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3947 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
3949 $code .= " ${v8ClassName}::namedPropertyGetterCustom(name, info);\n";
3951 $code .= " ${implClassName}V8Internal::namedPropertyGetter(name, info);\n";
3953 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3955 $implementation{nameSpaceInternal}->add($code);
3958 sub GenerateImplementationNamedPropertySetterCallback
3960 my $interface = shift;
3961 my $hasCustom = shift;
3962 my $implClassName = GetImplName($interface);
3963 my $v8ClassName = GetV8ClassName($interface);
3965 my $code = "static void namedPropertySetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3967 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
3969 $code .= " ${v8ClassName}::namedPropertySetterCustom(name, jsValue, info);\n";
3971 $code .= " ${implClassName}V8Internal::namedPropertySetter(name, jsValue, info);\n";
3973 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3975 $implementation{nameSpaceInternal}->add($code);
3978 sub GenerateImplementationNamedPropertyDeleterCallback
3980 my $interface = shift;
3981 my $hasCustom = shift;
3982 my $implClassName = GetImplName($interface);
3983 my $v8ClassName = GetV8ClassName($interface);
3985 my $code = "static void namedPropertyDeleterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
3987 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
3989 $code .= " ${v8ClassName}::namedPropertyDeleterCustom(name, info);\n";
3991 $code .= " ${implClassName}V8Internal::namedPropertyDeleter(name, info);\n";
3993 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3995 $implementation{nameSpaceInternal}->add($code);
3998 sub GenerateImplementationNamedPropertyEnumeratorCallback
4000 my $interface = shift;
4001 my $hasCustom = shift;
4002 my $implClassName = GetImplName($interface);
4003 my $v8ClassName = GetV8ClassName($interface);
4005 my $code = "static void namedPropertyEnumeratorCallback(const v8::PropertyCallbackInfo<v8::Array>& info)\n";
4007 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
4009 $code .= " ${v8ClassName}::namedPropertyEnumeratorCustom(info);\n";
4011 $code .= " ${implClassName}V8Internal::namedPropertyEnumerator(info);\n";
4013 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
4015 $implementation{nameSpaceInternal}->add($code);
4018 sub GenerateImplementationNamedPropertyQueryCallback
4020 my $interface = shift;
4021 my $hasCustom = shift;
4022 my $implClassName = GetImplName($interface);
4023 my $v8ClassName = GetV8ClassName($interface);
4025 my $code = "static void namedPropertyQueryCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)\n";
4027 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n";
4029 $code .= " ${v8ClassName}::namedPropertyQueryCustom(name, info);\n";
4031 $code .= " ${implClassName}V8Internal::namedPropertyQuery(name, info);\n";
4033 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
4035 $implementation{nameSpaceInternal}->add($code);
4038 sub GenerateMethodCall
4040 my $returnType = shift; # string or UnionType
4041 my $returnName = shift;
4042 my $functionExpression = shift;
4043 my $firstArgument = shift;
4044 my $raisesExceptions = shift;
4047 push @arguments, $firstArgument;
4048 if ($raisesExceptions) {
4049 push @arguments, "exceptionState";
4052 if (IsUnionType($returnType)) {
4054 my @extraArguments = ();
4055 for my $i (0..scalar(@{$returnType->unionMemberTypes})-1) {
4056 my $unionMemberType = $returnType->unionMemberTypes->[$i];
4057 my $nativeType = GetNativeType($unionMemberType);
4058 my $unionMemberVariable = $returnName . $i;
4059 my $unionMemberEnabledVariable = $returnName . $i . "Enabled";
4060 $code .= " bool ${unionMemberEnabledVariable} = false;\n";
4061 $code .= " ${nativeType} ${unionMemberVariable};\n";
4062 push @extraArguments, $unionMemberEnabledVariable;
4063 push @extraArguments, $unionMemberVariable;
4065 push @arguments, @extraArguments;
4066 $code .= " ${functionExpression}(" . (join ", ", @arguments) . ");";
4069 my $nativeType = GetNativeType($returnType);
4070 return " ${nativeType} result = ${functionExpression}(" . (join ", ", @arguments) . ");"
4074 sub GenerateImplementationNamedPropertyGetter
4076 my $interface = shift;
4077 my $namedGetterFunction = shift;
4078 my $implClassName = GetImplName($interface);
4079 my $v8ClassName = GetV8ClassName($interface);
4080 my $methodName = GetImplName($namedGetterFunction) || "anonymousNamedGetter";
4082 my $returnType = $namedGetterFunction->type;
4083 my $isNull = GenerateIsNullExpression($returnType, "result");
4084 my $nativeValue = "result";
4085 $nativeValue .= ".release()" if (IsRefPtrType($returnType));
4086 my $returnJSValueCode = NativeToJSValue($namedGetterFunction->type, $namedGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.GetIsolate()", "info", "imp", "", "return");
4087 my $raisesExceptions = $namedGetterFunction->extendedAttributes->{"RaisesException"};
4088 my $methodCallCode = GenerateMethodCall($returnType, "result", "imp->${methodName}", "propertyName", $raisesExceptions);
4090 my $code = "static void namedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
4092 if (!$interface->extendedAttributes->{"OverrideBuiltins"}) {
4093 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n";
4094 $code .= " return;\n";
4095 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty())\n";
4096 $code .= " return;\n";
4099 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());\n";
4100 $code .= " AtomicString propertyName = toCoreAtomicString(name);\n";
4101 if ($raisesExceptions) {
4102 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n";
4104 $code .= $methodCallCode . "\n";
4105 if ($raisesExceptions) {
4106 $code .= " if (exceptionState.throwIfNeeded())\n";
4107 $code .= " return;\n";
4109 $code .= " if (${isNull})\n";
4110 $code .= " return;\n";
4111 $code .= $returnJSValueCode . "\n";
4113 $implementation{nameSpaceInternal}->add($code);
4116 sub GenerateImplementationNamedPropertySetter
4118 my $interface = shift;
4119 my $namedSetterFunction = shift;
4120 my $implClassName = GetImplName($interface);
4121 my $v8ClassName = GetV8ClassName($interface);
4122 my $methodName = GetImplName($namedSetterFunction) || "anonymousNamedSetter";
4123 my $interfaceName = $interface->name;
4125 my $type = $namedSetterFunction->parameters->[1]->type;
4126 my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesException"};
4127 my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes->{"TreatNullAs"};
4128 my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttributes->{"TreatUndefinedAs"};
4130 my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
4132 if (!$interface->extendedAttributes->{"OverrideBuiltins"}) {
4133 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n";
4134 $code .= " return;\n";
4135 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty())\n";
4136 $code .= " return;\n";
4140 my $asSetterValue = 0;
4141 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());\n";
4142 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->type, $namedSetterFunction->extendedAttributes, $asSetterValue, "name", "propertyName", " ", "info.GetIsolate()");
4143 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->type, $namedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "propertyValue", " ", "info.GetIsolate()");
4145 my $extraArguments = "";
4146 if ($raisesExceptions || IsIntegerType($type)) {
4147 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n";
4148 if ($raisesExceptions) {
4149 $extraArguments = ", exceptionState";
4153 $code .= " bool result = imp->$methodName(propertyName, propertyValue$extraArguments);\n";
4154 if ($raisesExceptions) {
4155 $code .= " if (exceptionState.throwIfNeeded())\n";
4156 $code .= " return;\n";
4158 $code .= " if (!result)\n";
4159 $code .= " return;\n";
4160 $code .= " v8SetReturnValue(info, jsValue);\n";
4162 $implementation{nameSpaceInternal}->add($code);
4165 sub GenerateImplementationIndexedPropertyDeleter
4167 my $interface = shift;
4168 my $indexedDeleterFunction = shift;
4169 my $implClassName = GetImplName($interface);
4170 my $v8ClassName = GetV8ClassName($interface);
4171 my $methodName = GetImplName($indexedDeleterFunction) || "anonymousIndexedDeleter";
4173 my $raisesExceptions = $indexedDeleterFunction->extendedAttributes->{"RaisesException"};
4175 my $code = "static void indexedPropertyDeleter(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
4177 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());\n";
4178 my $extraArguments = "";
4179 if ($raisesExceptions) {
4180 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n";
4181 $extraArguments = ", exceptionState";
4183 $code .= " DeleteResult result = imp->${methodName}(index$extraArguments);\n";
4184 if ($raisesExceptions) {
4185 $code .= " if (exceptionState.throwIfNeeded())\n";
4186 $code .= " return;\n";
4188 $code .= " if (result != DeleteUnknownProperty)\n";
4189 $code .= " return v8SetReturnValueBool(info, result == DeleteSuccess);\n";
4191 $implementation{nameSpaceInternal}->add($code);
4194 sub GenerateImplementationNamedPropertyDeleter
4196 my $interface = shift;
4197 my $namedDeleterFunction = shift;
4198 my $implClassName = GetImplName($interface);
4199 my $v8ClassName = GetV8ClassName($interface);
4200 my $methodName = GetImplName($namedDeleterFunction) || "anonymousNamedDeleter";
4202 my $raisesExceptions = $namedDeleterFunction->extendedAttributes->{"RaisesException"};
4204 my $code = "static void namedPropertyDeleter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
4206 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());\n";
4207 $code .= " AtomicString propertyName = toCoreAtomicString(name);\n";
4208 my $extraArguments = "";
4209 if ($raisesExceptions) {
4210 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n";
4211 $extraArguments .= ", exceptionState";
4213 $code .= " DeleteResult result = imp->${methodName}(propertyName$extraArguments);\n";
4214 if ($raisesExceptions) {
4215 $code .= " if (exceptionState.throwIfNeeded())\n";
4216 $code .= " return;\n";
4218 $code .= " if (result != DeleteUnknownProperty)\n";
4219 $code .= " return v8SetReturnValueBool(info, result == DeleteSuccess);\n";
4221 $implementation{nameSpaceInternal}->add($code);
4224 sub GenerateImplementationNamedPropertyEnumerator
4226 my $interface = shift;
4227 my $implClassName = GetImplName($interface);
4228 my $v8ClassName = GetV8ClassName($interface);
4230 $implementation{nameSpaceInternal}->add(<<END);
4231 static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
4233 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
4234 Vector<String> names;
4235 ExceptionState exceptionState(info.Holder(), info.GetIsolate());
4236 imp->namedPropertyEnumerator(names, exceptionState);
4237 if (exceptionState.throwIfNeeded())
4239 v8::Handle<v8::Array> v8names = v8::Array::New(info.GetIsolate(), names.size());
4240 for (size_t i = 0; i < names.size(); ++i)
4241 v8names->Set(v8::Integer::New(info.GetIsolate(), i), v8String(info.GetIsolate(), names[i]));
4242 v8SetReturnValue(info, v8names);
4248 sub GenerateImplementationNamedPropertyQuery
4250 my $interface = shift;
4251 my $implClassName = GetImplName($interface);
4252 my $v8ClassName = GetV8ClassName($interface);
4254 $implementation{nameSpaceInternal}->add(<<END);
4255 static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)
4257 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
4258 AtomicString propertyName = toCoreAtomicString(name);
4259 ExceptionState exceptionState(info.Holder(), info.GetIsolate());
4260 bool result = imp->namedPropertyQuery(propertyName, exceptionState);
4261 if (exceptionState.throwIfNeeded())
4265 v8SetReturnValueInt(info, v8::None);
4271 sub GenerateImplementationLegacyCallAsFunction
4273 my $interface = shift;
4276 my $v8ClassName = GetV8ClassName($interface);
4278 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "LegacyCallAsFunction")) {
4279 $code .= " functionTemplate->InstanceTemplate()->SetCallAsFunctionHandler(${v8ClassName}::legacyCallCustom);\n";
4284 sub GenerateImplementationMarkAsUndetectable
4286 my $interface = shift;
4289 # Needed for legacy support of document.all
4290 if ($interface->name eq "HTMLAllCollection")
4292 $code .= " functionTemplate->InstanceTemplate()->MarkAsUndetectable();\n";
4297 sub GenerateImplementation
4300 my $interface = shift;
4301 my $interfaceName = $interface->name;
4302 my $implClassName = GetImplName($interface);
4303 my $v8ClassName = GetV8ClassName($interface);
4304 my $nativeType = GetNativeTypeForConversions($interface);
4306 AddToImplIncludes("RuntimeEnabledFeatures.h");
4307 AddToImplIncludes("bindings/v8/ExceptionState.h");
4308 AddToImplIncludes("core/dom/ContextFeatures.h");
4309 AddToImplIncludes("core/dom/Document.h");
4310 AddToImplIncludes("platform/TraceEvent.h");
4311 AddToImplIncludes("wtf/GetPtr.h");
4312 AddToImplIncludes("wtf/RefPtr.h");
4314 AddIncludesForType($interfaceName);
4315 if ($interface->extendedAttributes->{"CheckSecurity"}) {
4316 AddToImplIncludes("bindings/v8/BindingSecurity.h");
4319 my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObject") ? "${v8ClassName}::toActiveDOMObject" : "0";
4320 my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8ClassName}::toEventTarget" : "0";
4321 my $visitDOMWrapper = NeedsVisitDOMWrapper($interface) ? "${v8ClassName}::visitDOMWrapper" : "0";
4322 my $derefObject = "${v8ClassName}::derefObject";
4324 # Find the super descriptor.
4325 my $parentClass = "";
4326 my $parentClassTemplate = "";
4327 if ($interface->parent) {
4328 my $parent = $interface->parent;
4329 $parentClass = "V8" . $parent;
4330 $parentClassTemplate = $parentClass . "::domTemplate(isolate, currentWorldType)";
4333 my $parentClassInfo = $parentClass ? "&${parentClass}::wrapperTypeInfo" : "0";
4334 my $WrapperTypePrototype = $interface->isException ? "WrapperTypeExceptionPrototype" : "WrapperTypeObjectPrototype";
4336 if (!IsSVGTypeNeedingTearOff($interfaceName)) {
4338 static void initializeScriptWrappableForInterface(${implClassName}* object)
4340 if (ScriptWrappable::wrapperCanBeStoredInObject(object))
4341 ScriptWrappable::setTypeInfoInObject(object, &${v8ClassName}::wrapperTypeInfo);
4343 ASSERT_NOT_REACHED();
4346 } // namespace WebCore
4348 // In ScriptWrappable::init, the use of a local function declaration has an issue on Windows:
4349 // the local declaration does not pick up the surrounding namespace. Therefore, we provide this function
4350 // in the global namespace.
4351 // (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/feedback/details/664619/the-namespace-of-local-function-declarations-in-c)
4354 if (GetNamespaceForInterface($interface) eq "WebCore") {
4355 $code .= "void webCoreInitializeScriptWrappableForInterface(WebCore::${implClassName}* object)\n";
4357 $code .= "void webCoreInitializeScriptWrappableForInterface(${implClassName}* object)\n";
4362 WebCore::initializeScriptWrappableForInterface(object);
4367 $implementation{nameSpaceWebCore}->addHeader($code);
4370 my $code = "const WrapperTypeInfo ${v8ClassName}::wrapperTypeInfo = { gin::kEmbedderBlink, ${v8ClassName}::domTemplate, $derefObject, $toActiveDOMObject, $toEventTarget, ";
4371 $code .= "$visitDOMWrapper, ${v8ClassName}::installPerContextEnabledMethods, $parentClassInfo, $WrapperTypePrototype, ";
4372 $code .= IsWillBeGarbageCollectedType($interfaceName) ? "true" : "false";
4374 $implementation{nameSpaceWebCore}->addHeader($code);
4376 $implementation{nameSpaceInternal}->add("template <typename T> void V8_USE(T) { }\n\n");
4378 my $hasConstructors = 0;
4379 my $hasReplaceable = 0;
4381 # Generate property accessors for attributes.
4382 for (my $index = 0; $index < @{$interface->attributes}; $index++) {
4383 my $attribute = @{$interface->attributes}[$index];
4384 my $attrType = $attribute->type;
4385 my $attrExt = $attribute->extendedAttributes;
4387 # Generate special code for the constructor attributes.
4388 if ($attrType =~ /Constructor$/) {
4389 if (!HasCustomGetter($attrExt)) {
4390 $hasConstructors = 1;
4395 AddIncludesForType($attrType);
4397 if ($attrType eq "EventHandler" && $interfaceName eq "Window") {
4398 $attrExt->{"OnPrototype"} = 1;
4401 if ($attrType eq "SerializedScriptValue") {
4402 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
4405 my $isReplaceable = 0;
4406 if (!HasCustomSetter($attribute) && !$attrExt->{"PutForwards"} && $attrExt->{"Replaceable"}) {
4408 $hasReplaceable = 1;
4411 my $exposeJSAccessors = $attrExt->{"ExposeJSAccessors"};
4412 my @worldSuffixes = ("");
4413 if ($attrExt->{"PerWorldBindings"}) {
4414 push(@worldSuffixes, "ForMainWorld");
4416 foreach my $worldSuffix (@worldSuffixes) {
4417 GenerateNormalAttributeGetter($attribute, $interface, $worldSuffix, $exposeJSAccessors);
4418 GenerateNormalAttributeGetterCallback($attribute, $interface, $worldSuffix, $exposeJSAccessors);
4419 if (!$isReplaceable && !IsReadonly($attribute)) {
4420 GenerateNormalAttributeSetter($attribute, $interface, $worldSuffix, $exposeJSAccessors);
4421 GenerateNormalAttributeSetterCallback($attribute, $interface, $worldSuffix, $exposeJSAccessors);
4426 if ($hasConstructors) {
4427 GenerateConstructorGetter($interface);
4430 if ($hasConstructors || $hasReplaceable) {
4431 GenerateReplaceableAttributeSetter($interface);
4432 GenerateReplaceableAttributeSetterCallback($interface);
4435 if (NeedsVisitDOMWrapper($interface)) {
4436 GenerateVisitDOMWrapper($interface);
4439 if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne "Window") {
4440 GenerateSecurityCheckFunctions($interface);
4443 my @perContextEnabledFunctions;
4444 my @normalFunctions;
4445 my $needsDomainSafeFunctionSetter = 0;
4446 # Generate methods for functions.
4447 foreach my $function (@{$interface->functions}) {
4448 next if $function->name eq ""; # Skip anonymous special operations
4449 my @worldSuffixes = ("");
4450 if ($function->extendedAttributes->{"PerWorldBindings"}) {
4451 push(@worldSuffixes, "ForMainWorld");
4453 foreach my $worldSuffix (@worldSuffixes) {
4454 GenerateFunction($function, $interface, $worldSuffix);
4455 if ($function->{overloadIndex} == @{$function->{overloads}}) {
4456 if ($function->{overloadIndex} > 1) {
4457 GenerateOverloadedFunction($function, $interface, $worldSuffix);
4459 GenerateFunctionCallback($function, $interface, $worldSuffix);
4462 # If the function does not need domain security check, we need to
4463 # generate an access getter that returns different function objects
4464 # for different calling context.
4465 if ($interface->extendedAttributes->{"CheckSecurity"} && $function->extendedAttributes->{"DoNotCheckSecurity"} && (!HasCustomMethod($function->extendedAttributes) || $function->{overloadIndex} == 1)) {
4466 GenerateDomainSafeFunctionGetter($function, $interface, $worldSuffix);
4467 if (!$function->extendedAttributes->{"ReadOnly"}) {
4468 $needsDomainSafeFunctionSetter = 1;
4473 # Separate out functions that are enabled per context so we can process them specially.
4474 if ($function->extendedAttributes->{"PerContextEnabled"}) {
4475 push(@perContextEnabledFunctions, $function);
4477 push(@normalFunctions, $function);
4481 if ($needsDomainSafeFunctionSetter) {
4482 GenerateDomainSafeFunctionSetter($interface);
4486 my $attributes = $interface->attributes;
4488 # For the Window interface we partition the attributes into the
4489 # ones that disallows shadowing and the rest.
4490 my @disallowsShadowing;
4491 # Also separate out attributes that are enabled at runtime so we can process them specially.
4492 my @runtimeEnabledAttributes;
4493 my @perContextEnabledAttributes;
4494 my @normalAttributes;
4495 my @normalAccessors;
4496 my @staticAttributes;
4497 foreach my $attribute (@$attributes) {
4499 if ($attribute->isStatic) {
4500 push(@staticAttributes, $attribute);
4501 } elsif ($interfaceName eq "Window" && $attribute->extendedAttributes->{"Unforgeable"}) {
4502 push(@disallowsShadowing, $attribute);
4503 } elsif ($attribute->extendedAttributes->{"PerContextEnabled"}) {
4504 push(@perContextEnabledAttributes, $attribute);
4505 } elsif ($attribute->extendedAttributes->{"RuntimeEnabled"}) {
4506 push(@runtimeEnabledAttributes, $attribute);
4507 } elsif ($attribute->extendedAttributes->{"ExposeJSAccessors"}) {
4508 push(@normalAccessors, $attribute);
4510 push(@normalAttributes, $attribute);
4513 AddToImplIncludes("bindings/v8/V8DOMConfiguration.h");
4514 # Put the attributes that disallow shadowing on the shadow object.
4515 if (@disallowsShadowing) {
4517 $code .= "static const V8DOMConfiguration::AttributeConfiguration shadowAttributes[] = {\n";
4518 $code .= GenerateAttributeConfigurationArray($interface, \@disallowsShadowing);
4520 $implementation{nameSpaceWebCore}->add($code);
4523 my $hasAttributes = 0;
4524 if (@normalAttributes) {
4527 $code .= "static const V8DOMConfiguration::AttributeConfiguration ${v8ClassName}Attributes[] = {\n";
4528 $code .= GenerateAttributeConfigurationArray($interface, \@normalAttributes);
4530 $implementation{nameSpaceWebCore}->add($code);
4533 my $hasAccessors = 0;
4534 if (@normalAccessors) {
4537 $code .= "static const V8DOMConfiguration::AccessorConfiguration ${v8ClassName}Accessors[] = {\n";
4538 $code .= GenerateAttributeConfigurationArray($interface, \@normalAccessors, "accessor");
4540 $implementation{nameSpaceWebCore}->add($code);
4543 # Setup table of standard callback functions
4544 my $hasFunctions = 0;
4546 foreach my $function (@normalFunctions) {
4547 # Only one table entry is needed for overloaded functions:
4548 next if $function->{overloadIndex} > 1;
4549 # Don't put any nonstandard functions into this table:
4550 next if !IsStandardFunction($interface, $function);
4551 next if $function->name eq "";
4552 if (!$hasFunctions) {
4554 $code .= "static const V8DOMConfiguration::MethodConfiguration ${v8ClassName}Methods[] = {\n";
4556 my $name = $function->name;
4557 my $methodForMainWorld = "0";
4558 if ($function->extendedAttributes->{"PerWorldBindings"}) {
4559 $methodForMainWorld = "${implClassName}V8Internal::${name}MethodCallbackForMainWorld";
4561 my $functionLength = GetFunctionLength($function);
4562 my $conditionalString = GenerateConditionalString($function);
4563 $code .= "#if ${conditionalString}\n" if $conditionalString;
4565 {"$name", ${implClassName}V8Internal::${name}MethodCallback, ${methodForMainWorld}, ${functionLength}},
4567 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4569 $code .= "};\n\n" if $hasFunctions;
4570 $implementation{nameSpaceWebCore}->add($code);
4572 my $hasConstants = 0;
4573 if (@{$interface->constants}) {
4577 if (!HasCustomConstructor($interface)) {
4578 if ($interface->extendedAttributes->{"NamedConstructor"}) {
4579 GenerateNamedConstructor(@{$interface->constructors}[0], $interface);
4580 } elsif ($interface->extendedAttributes->{"Constructor"}) {
4581 GenerateConstructor($interface);
4582 } elsif ($interface->extendedAttributes->{"EventConstructor"}) {
4583 GenerateEventConstructor($interface);
4586 if (IsConstructable($interface)) {
4587 GenerateConstructorCallback($interface);
4590 my $accessCheck = "";
4591 if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne "Window") {
4592 $accessCheck = "instanceTemplate->SetAccessCheckCallbacks(${implClassName}V8Internal::namedSecurityCheck, ${implClassName}V8Internal::indexedSecurityCheck, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&${v8ClassName}::wrapperTypeInfo)));";
4595 # For the Window interface, generate the shadow object template
4596 # configuration method.
4597 if ($interfaceName eq "Window") {
4598 $implementation{nameSpaceWebCore}->add(<<END);
4599 static void configureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ, v8::Isolate* isolate, WrapperWorldType currentWorldType)
4601 V8DOMConfiguration::installAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttributes, WTF_ARRAY_LENGTH(shadowAttributes), isolate, currentWorldType);
4603 // Install a security handler with V8.
4604 templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&V8Window::wrapperTypeInfo)));
4605 templ->SetInternalFieldCount(V8Window::internalFieldCount);
4611 if (!$parentClassTemplate) {
4612 $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()";
4615 # Generate the template configuration method
4617 static void configure${v8ClassName}Template(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate, WrapperWorldType currentWorldType)
4619 functionTemplate->ReadOnlyPrototype();
4621 v8::Local<v8::Signature> defaultSignature;
4624 # Define constants, attributes, accessors and operations.
4625 my $runtimeEnabledIndent = "";
4626 if ($interface->extendedAttributes->{"RuntimeEnabled"}) {
4627 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($interface);
4628 $runtimeEnabledIndent = " ";
4630 if (!${runtimeEnabledFunction}())
4631 defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, \"\", $parentClassTemplate, ${v8ClassName}::internalFieldCount, 0, 0, 0, 0, 0, 0, isolate, currentWorldType);
4635 $code .= $runtimeEnabledIndent . " defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, \"${interfaceName}\", $parentClassTemplate, ${v8ClassName}::internalFieldCount,\n";
4636 $code .= $runtimeEnabledIndent . " " . ($hasAttributes ? "${v8ClassName}Attributes, WTF_ARRAY_LENGTH(${v8ClassName}Attributes),\n" : "0, 0,\n");
4637 $code .= $runtimeEnabledIndent . " " . ($hasAccessors ? "${v8ClassName}Accessors, WTF_ARRAY_LENGTH(${v8ClassName}Accessors),\n" : "0, 0,\n");
4638 $code .= $runtimeEnabledIndent . " " . ($hasFunctions ? "${v8ClassName}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods),\n" : "0, 0,\n");
4639 $code .= $runtimeEnabledIndent . " isolate, currentWorldType);\n";
4641 if (IsConstructable($interface)) {
4642 $code .= " functionTemplate->SetCallHandler(${v8ClassName}::constructorCallback);\n";
4643 my $interfaceLength = GetInterfaceLength($interface);
4644 $code .= " functionTemplate->SetLength(${interfaceLength});\n";
4648 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED instanceTemplate = functionTemplate->InstanceTemplate();
4649 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED prototypeTemplate = functionTemplate->PrototypeTemplate();
4653 $code .= " $accessCheck\n";
4656 # Define runtime enabled attributes.
4657 foreach my $runtimeEnabledAttribute (@runtimeEnabledAttributes) {
4658 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($runtimeEnabledAttribute);
4659 my $conditionalString = GenerateConditionalString($runtimeEnabledAttribute);
4660 $code .= "#if ${conditionalString}\n" if $conditionalString;
4661 $code .= " if (${runtimeEnabledFunction}()) {\n";
4662 $code .= " static const V8DOMConfiguration::AttributeConfiguration attributeConfiguration =\\\n";
4663 $code .= GenerateAttributeConfiguration($interface, $runtimeEnabledAttribute, ";", " ");
4665 V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate, attributeConfiguration, isolate, currentWorldType);
4668 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4671 my @runtimeEnabledConstants;
4672 if ($hasConstants) {
4674 $code .= " static const V8DOMConfiguration::ConstantConfiguration ${v8ClassName}Constants[] = {\n";
4675 foreach my $constant (@{$interface->constants}) {
4676 my $name = $constant->name;
4677 my $value = $constant->value;
4678 my $attrExt = $constant->extendedAttributes;
4679 my $implementedBy = $attrExt->{"ImplementedBy"};
4680 if ($implementedBy) {
4681 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
4682 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName));
4684 if ($attrExt->{"RuntimeEnabled"}) {
4685 push(@runtimeEnabledConstants, $constant);
4688 {"${name}", $value},
4694 V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate, ${v8ClassName}Constants, WTF_ARRAY_LENGTH(${v8ClassName}Constants), isolate);
4696 # Define runtime enabled constants.
4697 foreach my $runtimeEnabledConstant (@runtimeEnabledConstants) {
4698 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($runtimeEnabledConstant);
4699 my $name = $runtimeEnabledConstant->name;
4700 my $value = $runtimeEnabledConstant->value;
4701 $code .= " if (${runtimeEnabledFunction}()) {\n";
4703 static const V8DOMConfiguration::ConstantConfiguration constantConfiguration = {"${name}", static_cast<signed int>(${value})};
4704 V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate, &constantConfiguration, 1, isolate);
4708 $code .= join "", GenerateCompileTimeCheckForEnumsIfNeeded($interface);
4711 $code .= GenerateImplementationIndexedPropertyAccessors($interface);
4712 $code .= GenerateImplementationNamedPropertyAccessors($interface);
4713 $code .= GenerateImplementationLegacyCallAsFunction($interface);
4714 $code .= GenerateImplementationMarkAsUndetectable($interface);
4716 # Define operations.
4717 my $total_functions = 0;
4718 foreach my $function (@normalFunctions) {
4719 # Only one accessor is needed for overloaded operations.
4720 next if $function->{overloadIndex} > 1;
4721 next if $function->name eq "";
4724 next if IsStandardFunction($interface, $function);
4725 $code .= GenerateNonStandardFunction($interface, $function);
4728 # Define static attributes.
4729 foreach my $attribute (@staticAttributes) {
4730 $code .= GenerateStaticAttribute($interface, $attribute);
4734 if ($interfaceName eq "Window") {
4737 prototypeTemplate->SetInternalFieldCount(V8Window::internalFieldCount);
4738 functionTemplate->SetHiddenPrototype(true);
4739 instanceTemplate->SetInternalFieldCount(V8Window::internalFieldCount);
4740 // Set access check callbacks, but turned off initially.
4741 // When a context is detached from a frame, turn on the access check.
4742 // Turning on checks also invalidates inline caches of the object.
4743 instanceTemplate->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&V8Window::wrapperTypeInfo)), false);
4746 if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGlobalScope" or $interfaceName eq "SharedWorkerGlobalScope" or $interfaceName eq "ServiceWorkerGlobalScope") {
4748 functionTemplate->SetHiddenPrototype(true);
4754 // Custom toString template
4755 functionTemplate->Set(v8AtomicString(isolate, "toString"), V8PerIsolateData::current()->toStringTemplate());
4759 $implementation{nameSpaceWebCore}->add($code);
4761 AddToImplIncludes("bindings/v8/V8ObjectConstructor.h");
4762 $implementation{nameSpaceWebCore}->add(<<END);
4763 v8::Handle<v8::FunctionTemplate> ${v8ClassName}::domTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType)
4765 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
4766 V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWorldType).find(&wrapperTypeInfo);
4767 if (result != data->templateMap(currentWorldType).end())
4768 return result->value.newLocal(isolate);
4770 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4771 v8::EscapableHandleScope handleScope(isolate);
4772 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate, V8ObjectConstructor::isValidConstructorMode);
4773 configure${v8ClassName}Template(templ, isolate, currentWorldType);
4774 data->templateMap(currentWorldType).add(&wrapperTypeInfo, UnsafePersistent<v8::FunctionTemplate>(isolate, templ));
4775 return handleScope.Escape(templ);
4778 bool ${v8ClassName}::hasInstance(v8::Handle<v8::Value> jsValue, v8::Isolate* isolate)
4780 return V8PerIsolateData::from(isolate)->hasInstanceInMainWorld(&wrapperTypeInfo, jsValue)
4781 || V8PerIsolateData::from(isolate)->hasInstanceInNonMainWorld(&wrapperTypeInfo, jsValue);
4786 if (@perContextEnabledAttributes) {
4789 void ${v8ClassName}::installPerContextEnabledProperties(v8::Handle<v8::Object> instanceTemplate, ${nativeType}* impl, v8::Isolate* isolate)
4791 v8::Local<v8::Object> prototypeTemplate = v8::Local<v8::Object>::Cast(instanceTemplate->GetPrototype());
4794 # Define per-context enabled attributes.
4795 foreach my $perContextEnabledAttribute (@perContextEnabledAttributes) {
4796 my $contextEnabledFunction = GetContextEnabledFunctionName($perContextEnabledAttribute);
4797 $code .= " if (${contextEnabledFunction}(impl->document())) {\n";
4799 $code .= " static const V8DOMConfiguration::AttributeConfiguration attributeConfiguration =\\\n";
4800 $code .= GenerateAttributeConfiguration($interface, $perContextEnabledAttribute, ";", " ");
4802 V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate, attributeConfiguration, isolate);
4810 $implementation{nameSpaceWebCore}->add($code);
4813 if (@perContextEnabledFunctions) {
4816 void ${v8ClassName}::installPerContextEnabledMethods(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate)
4819 # Define per-context enabled operations.
4821 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(isolate, domTemplate(isolate, worldType(isolate)));
4823 ExecutionContext* context = toExecutionContext(prototypeTemplate->CreationContext());
4826 foreach my $perContextEnabledFunction (@perContextEnabledFunctions) {
4827 my $contextEnabledFunction = GetContextEnabledFunctionName($perContextEnabledFunction);
4828 my $functionLength = GetFunctionLength($perContextEnabledFunction);
4829 my $conditionalString = GenerateConditionalString($perContextEnabledFunction);
4830 $code .= "\n#if ${conditionalString}\n" if $conditionalString;
4831 $code .= " if (context && context->isDocument() && ${contextEnabledFunction}(toDocument(context)))\n";
4832 my $name = $perContextEnabledFunction->name;
4834 prototypeTemplate->Set(v8AtomicString(isolate, "$name"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), defaultSignature, $functionLength)->GetFunction());
4836 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4843 $implementation{nameSpaceWebCore}->add($code);
4846 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
4847 $implementation{nameSpaceWebCore}->add(<<END);
4848 ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> wrapper)
4850 return toNative(wrapper);
4856 if (InheritsInterface($interface, "EventTarget")) {
4857 $implementation{nameSpaceWebCore}->add(<<END);
4858 EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object)
4860 return toNative(object);
4866 if ($interfaceName eq "Window") {
4867 $implementation{nameSpaceWebCore}->add(<<END);
4868 v8::Handle<v8::ObjectTemplate> V8Window::getShadowObjectTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType)
4870 if (currentWorldType == MainWorld) {
4871 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForMainWorld, ());
4872 if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) {
4873 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4874 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
4875 configureShadowObjectTemplate(templ, isolate, currentWorldType);
4876 V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ);
4879 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForMainWorld);
4881 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForNonMainWorld, ());
4882 if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) {
4883 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4884 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
4885 configureShadowObjectTemplate(templ, isolate, currentWorldType);
4886 V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ);
4889 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForNonMainWorld);
4896 GenerateSpecialWrap($interface, $v8ClassName);
4897 GenerateToV8Converters($interface, $v8ClassName);
4899 $implementation{nameSpaceWebCore}->add("void ${v8ClassName}::derefObject(void* object)\n");
4900 $implementation{nameSpaceWebCore}->add("{\n");
4901 if (IsWillBeGarbageCollectedType($interface->name)) {
4902 $implementation{nameSpaceWebCore}->add("#if !ENABLE(OILPAN)\n");
4904 $implementation{nameSpaceWebCore}->add(" fromInternalPointer(object)->deref();\n");
4905 if (IsWillBeGarbageCollectedType($interface->name)) {
4906 $implementation{nameSpaceWebCore}->add("#endif // !ENABLE(OILPAN)\n");
4908 $implementation{nameSpaceWebCore}->add("}\n\n");
4910 $implementation{nameSpaceWebCore}->add(<<END);
4912 v8::Handle<v8::Value> toV8NoInline(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
4914 return toV8(impl, creationContext, isolate);
4920 sub GenerateHeaderContentHeader
4922 my $interface = shift;
4923 my $v8ClassName = GetV8ClassName($interface);
4924 my $conditionalString = GenerateConditionalString($interface);
4926 my @headerContentHeader = split("\r", $licenseHeader);
4928 push(@headerContentHeader, "#ifndef ${v8ClassName}" . "_h\n");
4929 push(@headerContentHeader, "#define ${v8ClassName}" . "_h\n\n");
4930 push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalString;
4931 return join "", @headerContentHeader;
4934 sub GenerateCallbackHeader
4937 my $interface = shift;
4939 my $interfaceName = $interface->name;
4940 my $implClassName = GetImplName($interface);
4941 my $v8ClassName = GetV8ClassName($interface);
4944 push(@includes, "bindings/v8/ActiveDOMCallback.h");
4945 push(@includes, "bindings/v8/DOMWrapperWorld.h");
4946 push(@includes, "bindings/v8/ScopedPersistent.h");
4947 push(@includes, HeaderFilesForInterface($interfaceName, $implClassName));
4948 for my $include (sort @includes) {
4949 $header{includes}->add("#include \"$include\"\n");
4951 $header{nameSpaceWebCore}->addHeader("\nclass ExecutionContext;\n");
4952 $header{class}->addHeader("class $v8ClassName FINAL : public $implClassName, public ActiveDOMCallback {");
4953 $header{class}->addFooter("};\n");
4955 $header{classPublic}->add(<<END);
4956 static PassOwnPtr<${v8ClassName}> create(v8::Handle<v8::Function> callback, ExecutionContext* context)
4959 return adoptPtr(new ${v8ClassName}(callback, context));
4962 virtual ~${v8ClassName}();
4967 my $numFunctions = @{$interface->functions};
4968 if ($numFunctions > 0) {
4969 foreach my $function (@{$interface->functions}) {
4970 my $code = " virtual " . GetNativeTypeForCallbacks($function->type) . " " . $function->name . "(";
4973 if (ExtendedAttributeContains($function->extendedAttributes->{"CallWith"}, "ThisValue")) {
4974 push(@args, GetNativeType("any") . " thisValue");
4976 my @params = @{$function->parameters};
4977 foreach my $param (@params) {
4978 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
4980 $code .= join(", ", @args);
4981 $code .= ") OVERRIDE;\n";
4982 $header{classPublic}->add($code);
4986 $header{classPrivate}->add(<<END);
4987 ${v8ClassName}(v8::Handle<v8::Function>, ExecutionContext*);
4989 v8::Isolate* m_isolate;
4990 ScopedPersistent<v8::Function> m_callback;
4991 RefPtr<DOMWrapperWorld> m_world;
4995 sub GenerateCallbackImplementation
4998 my $interface = shift;
4999 my $v8ClassName = GetV8ClassName($interface);
5001 AddToImplIncludes("core/dom/ExecutionContext.h");
5002 AddToImplIncludes("bindings/v8/V8Binding.h");
5003 AddToImplIncludes("bindings/v8/V8Callback.h");
5004 AddToImplIncludes("wtf/Assertions.h");
5005 AddToImplIncludes("wtf/GetPtr.h");
5006 AddToImplIncludes("wtf/RefPtr.h");
5008 $implementation{nameSpaceWebCore}->add(<<END);
5009 ${v8ClassName}::${v8ClassName}(v8::Handle<v8::Function> callback, ExecutionContext* context)
5010 : ActiveDOMCallback(context)
5011 , m_isolate(toIsolate(context))
5012 , m_callback(m_isolate, callback)
5013 , m_world(DOMWrapperWorld::current(m_isolate))
5019 $implementation{nameSpaceWebCore}->add(<<END);
5020 ${v8ClassName}::~${v8ClassName}()
5027 my $numFunctions = @{$interface->functions};
5028 if ($numFunctions > 0) {
5029 foreach my $function (@{$interface->functions}) {
5031 my @params = @{$function->parameters};
5033 # Add includes for types even if custom
5034 AddIncludesForType($function->type);
5035 foreach my $param (@params) {
5036 AddIncludesForType($param->type);
5038 next if $function->extendedAttributes->{"Custom"};
5040 die "We only support callbacks that return boolean or void values.\n" unless ($function->type eq "boolean" || $function->type eq "void");
5041 my $defaultReturn = $function->type eq "boolean" ? " true" : "";
5042 $code .= GetNativeTypeForCallbacks($function->type) . " ${v8ClassName}::" . $function->name . "(";
5043 my $callWithThisValue = ExtendedAttributeContains($function->extendedAttributes->{"CallWith"}, "ThisValue");
5046 if ($callWithThisValue) {
5047 push(@args, GetNativeTypeForCallbacks("any") . " thisValue");
5049 foreach my $param (@params) {
5050 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name);
5052 $code .= join(", ", @args);
5056 $code .= " if (!canInvokeCallback())\n";
5057 $code .= " return${defaultReturn};\n\n";
5058 $code .= " v8::HandleScope handleScope(m_isolate);\n\n";
5059 $code .= " v8::Handle<v8::Context> v8Context = toV8Context(executionContext(), m_world.get());\n";
5060 $code .= " if (v8Context.IsEmpty())\n";
5061 $code .= " return${defaultReturn};\n\n";
5062 $code .= " v8::Context::Scope scope(v8Context);\n";
5064 my $thisObjectHandle = "";
5065 if ($callWithThisValue) {
5066 $code .= " v8::Handle<v8::Value> thisHandle = thisValue.v8Value();\n";
5067 $code .= " if (thisHandle.IsEmpty()) {\n";
5068 $code .= " if (!isScriptControllerTerminating())\n";
5069 $code .= " CRASH();\n";
5070 $code .= " return${defaultReturn};\n";
5072 $code .= " ASSERT(thisHandle->IsObject());\n";
5073 $thisObjectHandle = "v8::Handle<v8::Object>::Cast(thisHandle), ";
5076 foreach my $param (@params) {
5077 my $paramName = $param->name;
5078 $code .= NativeToJSValue($param->type, $param->extendedAttributes, $paramName, " ", "v8::Handle<v8::Value> ${paramName}Handle =", "m_isolate", "") . "\n";
5079 $code .= " if (${paramName}Handle.IsEmpty()) {\n";
5080 $code .= " if (!isScriptControllerTerminating())\n";
5081 $code .= " CRASH();\n";
5082 $code .= " return${defaultReturn};\n";
5084 push(@args, "${paramName}Handle");
5087 if (scalar(@args) > 0) {
5088 $code .= " v8::Handle<v8::Value> argv[] = { ";
5089 $code .= join(", ", @args);
5092 $code .= " v8::Handle<v8::Value> *argv = 0;\n\n";
5095 if ($function->type eq "boolean") {
5098 $code .= "invokeCallback(m_callback.newLocal(m_isolate), ${thisObjectHandle}" . scalar(@args) . ", argv, executionContext(), m_isolate);\n";
5100 $implementation{nameSpaceWebCore}->add($code);
5105 sub GenerateSpecialWrap
5107 my $interface = shift;
5108 my $v8ClassName = shift;
5109 my $nativeType = GetNativeTypeForConversions($interface);
5111 my $specialWrap = $interface->extendedAttributes->{"SpecialWrapFor"};
5112 my $isDocument = InheritsInterface($interface, "Document");
5113 if (!$specialWrap && !$isDocument) {
5119 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
5124 foreach my $type (split(/\s*\|\s*/, $specialWrap)) {
5125 AddToImplIncludes("V8${type}.h");
5127 if (impl->is${type}())
5128 return wrap(to${type}(impl), creationContext, isolate);
5133 v8::Handle<v8::Object> wrapper = ${v8ClassName}::createWrapper(impl, creationContext, isolate);
5136 AddToImplIncludes("bindings/v8/ScriptController.h");
5137 AddToImplIncludes("bindings/v8/V8WindowShell.h");
5139 if (wrapper.IsEmpty())
5141 DOMWrapperWorld* world = DOMWrapperWorld::current(isolate);
5142 if (world->isMainWorld()) {
5143 if (Frame* frame = impl->frame())
5144 frame->script().windowShell(world)->updateDocumentWrapper(wrapper);
5153 $implementation{nameSpaceWebCore}->add($code);
5156 sub GenerateToV8Converters
5158 my $interface = shift;
5159 my $v8ClassName = shift;
5160 my $interfaceName = $interface->name;
5162 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "ToV8")) {
5166 my $passRefPtrType = GetPassRefPtrType($interface);
5168 # FIXME: Do we really need to treat /SVG/ as dependent DOM objects?
5169 my $wrapperConfiguration = "WrapperConfiguration::Independent";
5170 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")
5171 || InheritsExtendedAttribute($interface, "DependentLifetime")
5172 || NeedsVisitDOMWrapper($interface)
5173 || $v8ClassName =~ /SVG/) {
5174 $wrapperConfiguration = "WrapperConfiguration::Dependent";
5179 v8::Handle<v8::Object> ${v8ClassName}::createWrapper(${passRefPtrType} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
5182 ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl.get(), isolate));
5183 if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) {
5184 const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObject(impl.get());
5185 // Might be a XXXConstructor::wrapperTypeInfo instead of an XXX::wrapperTypeInfo. These will both have
5186 // the same object de-ref functions, though, so use that as the basis of the check.
5187 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == wrapperTypeInfo.derefObjectFunction);
5192 if (InheritsInterface($interface, "Document")) {
5193 AddToImplIncludes("bindings/v8/ScriptController.h");
5194 AddToImplIncludes("core/frame/Frame.h");
5196 if (Frame* frame = impl->frame()) {
5197 if (frame->script().initializeMainWorld()) {
5198 // initializeMainWorld may have created a wrapper for the object, retry from the start.
5199 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper<${v8ClassName}>(impl.get(), isolate);
5200 if (!wrapper.IsEmpty())
5208 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, &wrapperTypeInfo, toInternalPointer(impl.get()), isolate);
5209 if (UNLIKELY(wrapper.IsEmpty()))
5213 if (InheritsInterface($interface, "AudioBuffer")) {
5214 AddToImplIncludes("modules/webaudio/AudioBuffer.h");
5216 for (unsigned i = 0, n = impl->numberOfChannels(); i < n; i++) {
5217 Float32Array* channelData = impl->getChannelData(i);
5218 channelData->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
5225 installPerContextEnabledProperties(wrapper, impl.get(), isolate);
5226 V8DOMWrapper::associateObjectWithWrapper<$v8ClassName>(impl, &wrapperTypeInfo, wrapper, isolate, $wrapperConfiguration);
5231 $implementation{nameSpaceWebCore}->add($code);
5234 sub GenerateSecurityCheckFunctions
5236 my $interface = shift;
5237 my $implClassName = GetImplName($interface);
5238 my $v8ClassName = GetV8ClassName($interface);
5240 AddToImplIncludes("bindings/v8/BindingSecurity.h");
5241 $implementation{nameSpaceInternal}->add(<<END);
5242 bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>)
5244 $implClassName* imp = ${v8ClassName}::toNative(host);
5245 return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(), imp->frame(), DoNotReportSecurityError);
5249 $implementation{nameSpaceInternal}->add(<<END);
5250 bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>)
5252 $implClassName* imp = ${v8ClassName}::toNative(host);
5253 return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(), imp->frame(), DoNotReportSecurityError);
5259 sub GetNativeTypeForConversions
5261 my $interface = shift;
5262 my $implClassName = GetImplName($interface);
5263 $implClassName = GetSVGTypeNeedingTearOff($interface->name) if IsSVGTypeNeedingTearOff($interface->name);
5264 return $implClassName;
5267 sub GetNamespaceForInterface
5269 my $interface = shift;
5270 return "WTF" if IsTypedArrayType($interface->name);
5274 sub GenerateFunctionCallString
5276 my $function = shift;
5277 my $numberOfParameters = shift;
5279 my $interface = shift;
5280 my $forMainWorldSuffix = shift;
5281 my $hasExceptionState = shift;
5282 my %replacements = @_;
5284 my $interfaceName = $interface->name;
5285 my $implClassName = GetImplName($interface);
5286 my $name = GetImplName($function);
5287 my $returnType = $function->type;
5289 my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interfaceName =~ /List$/);
5292 my $humanFriendlyIndex = $index + 1;
5296 my $implementedBy = $function->extendedAttributes->{"ImplementedBy"};
5297 if ($implementedBy) {
5298 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy);
5299 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName));
5300 unshift(@arguments, "imp") if !$function->isStatic;
5301 $functionName = "${implementedByImplName}::${name}";
5302 } elsif ($function->isStatic) {
5303 $functionName = "${implClassName}::${name}";
5305 $functionName = "imp->${name}";
5308 my $callWith = $function->extendedAttributes->{"CallWith"};
5309 my ($callWithArgs, $subCode) = GenerateCallWith($callWith, $indent, 1, $function);
5311 unshift(@arguments, @$callWithArgs);
5312 $index += @$callWithArgs;
5313 $humanFriendlyIndex = $index + 1;
5315 $numberOfParameters += @$callWithArgs;
5317 foreach my $parameter (@{$function->parameters}) {
5318 if ($index eq $numberOfParameters) {
5321 my $paramName = $parameter->name;
5322 my $paramType = $parameter->type;
5324 if ($replacements{$paramName}) {
5325 push @arguments, $replacements{$paramName};
5326 } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceName =~ /List$/) {
5327 push @arguments, "$paramName->propertyReference()";
5328 if ($hasExceptionState) {
5331 exceptionState.throwTypeError(\"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }'.\");
5332 exceptionState.throwIfNeeded();
5339 throwTypeError(ExceptionMessages::failedToExecute(\"$name\", \"$interfaceName\", \"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }'.\"), info.GetIsolate());
5344 } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTransformList") {
5345 push @arguments, "$paramName.get()";
5346 } elsif (IsNullableParameter($parameter)) {
5347 push @arguments, "${paramName}IsNull ? 0 : &$paramName";
5348 } elsif (IsCallbackInterface($paramType) or $paramType eq "NodeFilter" or $paramType eq "XPathNSResolver") {
5349 push @arguments, "$paramName.release()";
5351 push @arguments, $paramName;
5354 $humanFriendlyIndex = $index + 1;
5357 # Support for returning a union type.
5358 if (IsUnionType($returnType)) {
5359 my $types = $returnType->unionMemberTypes;
5360 for my $i (0 .. scalar(@$types)-1) {
5361 my $unionMemberType = $types->[$i];
5362 my $unionMemberNativeType = GetNativeType($unionMemberType);
5363 my $unionMemberNumber = $i + 1;
5364 my $unionMemberVariable = "result" . $i;
5365 my $unionMemberEnabledVariable = "result" . $i . "Enabled";
5366 $code .= " bool ${unionMemberEnabledVariable} = false;\n";
5367 $code .= " ${unionMemberNativeType} ${unionMemberVariable};\n";
5368 push @arguments, $unionMemberEnabledVariable;
5369 push @arguments, $unionMemberVariable;
5373 if ($function->extendedAttributes->{"RaisesException"}) {
5374 push @arguments, "exceptionState";
5377 my $functionString = "$functionName(" . join(", ", @arguments) . ")";
5379 my $return = "result";
5380 my $returnIsRef = IsRefPtrType($returnType);
5382 if ($returnType eq "void" || IsUnionType($returnType)) {
5383 $code .= $indent . "$functionString;\n";
5384 } elsif (ExtendedAttributeContains($callWith, "ScriptState") or $function->extendedAttributes->{"RaisesException"}) {
5385 my $nativeReturnType = GetNativeType($returnType, {}, "");
5386 $nativeReturnType = GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType;
5388 $code .= $indent . $nativeReturnType . " result = $functionString;\n";
5390 # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary
5391 $return = $functionString;
5394 if ($interfaceName eq "SVGTransformList" and IsRefPtrType($returnType)) {
5395 $return = "WTF::getPtr(" . $return . ")";
5399 if ($function->extendedAttributes->{"RaisesException"}) {
5400 $code .= $indent . "if (exceptionState.throwIfNeeded())\n";
5401 $code .= $indent . " return;\n";
5404 if (ExtendedAttributeContains($callWith, "ScriptState")) {
5405 $code .= $indent . "if (state.hadException()) {\n";
5406 $code .= $indent . " v8::Local<v8::Value> exception = state.exception();\n";
5407 $code .= $indent . " state.clearException();\n";
5408 $code .= $indent . " throwError(exception, info.GetIsolate());\n";
5409 $code .= $indent . " return;\n";
5410 $code .= $indent . "}\n";
5413 if ($isSVGTearOffType) {
5414 AddToImplIncludes("V8$returnType.h");
5415 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h");
5416 my $svgNativeType = GetSVGTypeNeedingTearOff($returnType);
5417 # FIXME: Update for all ScriptWrappables.
5418 if (IsDOMNodeType($interfaceName)) {
5419 if ($forMainWorldSuffix eq "ForMainWorld") {
5420 $code .= $indent . "v8SetReturnValueForMainWorld(info, WTF::getPtr(${svgNativeType}::create($return)));\n";
5422 $code .= $indent . "v8SetReturnValueFast(info, WTF::getPtr(${svgNativeType}::create($return)), imp);\n";
5425 $code .= $indent . "v8SetReturnValue${forMainWorldSuffix}(info, WTF::getPtr(${svgNativeType}::create($return)));\n";
5430 # If the implementing class is a POD type, commit changes
5431 if (IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$/) {
5432 $code .= $indent . "wrapper->commitChange();\n";
5435 $return .= ".release()" if ($returnIsRef);
5438 # FIXME: Update for all ScriptWrappables.
5439 if (IsDOMNodeType($interfaceName)) {
5440 $nativeValue = NativeToJSValue($function->type, $function->extendedAttributes, $return, $indent, "", "info.GetIsolate()", "info", "imp", $forMainWorldSuffix, "return");
5442 $nativeValue = NativeToJSValue($function->type, $function->extendedAttributes, $return, $indent, "", "info.GetIsolate()", "info", 0, $forMainWorldSuffix, "return");
5445 $code .= $nativeValue . "\n" if $nativeValue; # Skip blank line for void return type
5453 my $extendedAttributes = shift;
5454 my $isParameter = shift;
5456 my $svgNativeType = GetSVGTypeNeedingTearOff($type);
5457 if ($svgNativeType) {
5458 if ($svgNativeType =~ /List$/) {
5459 return "${svgNativeType}*";
5461 return "RefPtr<${svgNativeType} >";
5465 return "float" if $type eq "float";
5466 return "double" if $type eq "double";
5467 return "int" if $type eq "long" or $type eq "int" or $type eq "short" or $type eq "byte";
5468 if ($type eq "unsigned long" or $type eq "unsigned int" or $type eq "unsigned short" or $type eq "octet") {
5471 return "long long" if $type eq "long long";
5472 return "unsigned long long" if $type eq "unsigned long long";
5473 return "bool" if $type eq "boolean";
5475 if (($type eq "DOMString" || IsEnumType($type)) and $isParameter) {
5476 my $mode = GetV8StringResourceMode($extendedAttributes);
5477 # FIXME: Add the case for 'elsif ($attributeOrParameter->extendedAttributes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes->{"TreatUndefinedAs"} eq "NullString"))'.
5478 return "V8StringResource<$mode>";
5481 return "String" if $type eq "DOMString" or IsEnumType($type);
5483 return "ScriptPromise" if $type eq "Promise";
5485 return "Range::CompareHow" if $type eq "CompareHow";
5486 return "DOMTimeStamp" if $type eq "DOMTimeStamp";
5487 return "double" if $type eq "Date";
5488 return "ScriptValue" if $type eq "any" or IsCallbackFunctionType($type);
5489 return "Dictionary" if $type eq "Dictionary";
5491 die "UnionType is not supported" if IsUnionType($type);
5493 if (IsTypedArrayType($type)) {
5494 return $isParameter ? "${type}*" : "RefPtr<${type}>";
5497 # We need to check [ImplementedAs] extended attribute for wrapper types.
5498 return "RefPtr<$type>" if $type eq "XPathNSResolver"; # FIXME: can this be put in nonWrapperTypes instead?
5499 if (IsWrapperType($type)) {
5500 my $interface = ParseInterface($type);
5501 my $implClassName = GetImplName($interface);
5503 return "$implClassName*";
5504 } elsif (IsWillBeGarbageCollectedType($interface->name)) {
5505 return "RefPtrWillBeRawPtr<$implClassName>";
5507 return "RefPtr<$implClassName>";
5510 return "RefPtr<$type>" if IsRefPtrType($type) and (not $isParameter or $nonWrapperTypes{$type});
5512 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5514 if ($arrayOrSequenceType) {
5515 my $nativeType = GetNativeType($arrayOrSequenceType);
5516 $nativeType .= " " if ($nativeType =~ />$/);
5517 return "Vector<${nativeType}>";
5520 # Default, assume native type is a pointer with same type name as idl type
5524 sub GetNativeTypeForCallbacks
5527 return "const String&" if $type eq "DOMString";
5528 return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
5529 return "void" if $type eq "void";
5531 # Callbacks use raw pointers, so pass isParameter = 1
5532 my $nativeType = GetNativeType($type, {}, "parameter");
5533 return "const $nativeType&" if $nativeType =~ /^Vector/;
5537 sub JSValueToNativeStatement
5540 my $extendedAttributes = shift;
5541 my $argIndexOrZero = shift;
5542 my $jsValue = shift;
5543 my $variableName = shift;
5545 my $getIsolate = shift;
5547 my $nativeType = GetNativeType($type, $extendedAttributes, "parameter");
5548 my $native_value = JSValueToNative($type, $extendedAttributes, $argIndexOrZero, $jsValue, $getIsolate);
5550 if ($type eq "DOMString" || IsEnumType($type)) {
5551 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/;
5552 if ($type eq "DOMString" or IsEnumType($type)) {
5553 $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $native_value);\n"
5555 $code .= $indent . "$nativeType $variableName($native_value, true);\n";
5557 } elsif (IsIntegerType($type)) {
5558 $code .= $indent . "V8TRYCATCH_EXCEPTION_VOID($nativeType, $variableName, $native_value, exceptionState);\n";
5560 $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_value);\n";
5569 my $extendedAttributes = shift;
5570 # Argument position (1-indexed) or 0 if for a setter's value.
5571 my $argIndexOrZero = shift;
5573 my $getIsolate = shift;
5575 return "$value->BooleanValue()" if $type eq "boolean";
5576 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
5578 if (IsIntegerType($type)) {
5579 my $conversion = "to" . $integerTypeHash{$type} . "($value";
5580 if ($extendedAttributes->{"EnforceRange"}) {
5581 return "${conversion}, EnforceRange, exceptionState)";
5583 return "${conversion}, exceptionState)";
5586 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
5587 return "toCoreDate($value)" if $type eq "Date";
5589 if ($type eq "DOMString" or IsEnumType($type)) {
5593 if ($type eq "SerializedScriptValue") {
5594 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
5595 return "SerializedScriptValue::create($value, $getIsolate)";
5598 if ($type eq "Dictionary") {
5599 AddToImplIncludes("bindings/v8/Dictionary.h");
5600 return "Dictionary($value, $getIsolate)";
5603 if ($type eq "any" || IsCallbackFunctionType($type)) {
5604 AddToImplIncludes("bindings/v8/ScriptValue.h");
5605 return "ScriptValue($value, $getIsolate)";
5608 if ($type eq "Promise") {
5609 AddToImplIncludes("bindings/v8/ScriptPromise.h");
5610 return "ScriptPromise($value, $getIsolate)";
5613 if ($type eq "NodeFilter") {
5614 return "toNodeFilter($value, $getIsolate)";
5617 if ($type eq "Window") {
5618 return "toDOMWindow($value, $getIsolate)";
5621 if ($type eq "MediaQueryListListener") {
5622 AddToImplIncludes("core/css/MediaQueryListListener.h");
5623 return "MediaQueryListListener::create(ScriptValue(" . $value . ", $getIsolate))";
5626 if ($type eq "EventTarget") {
5627 return "V8DOMWrapper::isDOMWrapper($value) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast($value))->toEventTarget(v8::Handle<v8::Object>::Cast($value)) : 0";
5630 if (IsTypedArrayType($type)) {
5631 AddIncludesForType($type);
5632 return "$value->Is${type}() ? V8${type}::toNative(v8::Handle<v8::${type}>::Cast($value)) : 0"
5635 if ($type eq "XPathNSResolver") {
5636 return "toXPathNSResolver($value, $getIsolate)";
5639 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5641 if ($arrayOrSequenceType) {
5642 if (IsRefPtrType($arrayOrSequenceType)) {
5643 AddToImplIncludes("V8${arrayOrSequenceType}.h");
5644 return "(toRefPtrNativeArray<${arrayOrSequenceType}, V8${arrayOrSequenceType}>($value, $argIndexOrZero, $getIsolate))";
5646 return "toNativeArray<" . GetNativeType($arrayOrSequenceType) . ">($value, $argIndexOrZero, $getIsolate)";
5649 AddIncludesForType($type);
5651 AddToImplIncludes("V8${type}.h");
5652 return "V8${type}::hasInstance($value, $getIsolate) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
5657 my $type = shift; # string or UnionType
5658 if(ref($type) eq "UnionType") {
5659 die "Currently only 2 values of non-union type is supported as union type.\n" unless @{$type->unionMemberTypes} == 2;
5668 return 0 if GetArrayType($type);
5669 return 0 if GetSequenceType($type);
5670 return 0 if IsCallbackFunctionType($type);
5671 return 0 if IsEnumType($type);
5672 return 0 if IsPrimitiveType($type);
5673 return 0 if $type eq "Promise";
5674 return !$nonWrapperTypes{$type};
5677 sub IsCallbackInterface
5680 return 0 unless IsWrapperType($type);
5681 return 0 if IsTypedArrayType($type);
5683 my $idlFile = IDLFileForInterface($type)
5684 or die("Could NOT find IDL file for interface \"$type\"!\n");
5686 open FILE, "<", $idlFile;
5690 my $fileContents = join('', @lines);
5691 return ($fileContents =~ /callback\s+interface\s+(\w+)\s*{/gs);
5694 sub GetNativeTypeOfTypedArray
5696 my $interface = shift;
5697 my $interfaceName = $interface->name;
5698 die "TypedArray of unknown type is found" unless $typedArrayHash{$interface->name};
5699 return @{$typedArrayHash{$interface->name}};
5706 return 1 if $domNodeTypes{$type};
5707 return 1 if $type =~ /^HTML.*Element$/;
5708 return 1 if $type =~ /^SVG.*Element$/;
5717 my $extendedAttributes = shift;
5718 my $nativeValue = shift;
5719 my $indent = shift; # added before every line
5720 my $receiver = shift; # "return" or "<variableName> ="
5721 my $getIsolate = shift;
5722 die "An Isolate is mandatory for native value => JS value conversion." unless $getIsolate;
5723 my $getCallbackInfo = shift || "";
5724 my $creationContext = $getCallbackInfo ? "${getCallbackInfo}.Holder()" : "v8::Handle<v8::Object>()";
5725 my $getScriptWrappable = shift || "";
5726 my $forMainWorldSuffix = shift || "";
5727 my $returnValueArg = shift || 0;
5728 my $isReturnValue = $returnValueArg eq "return";
5730 if (IsUnionType($type)) {
5731 my $types = $type->unionMemberTypes;
5733 for my $i (0 .. scalar(@$types)-1) {
5734 my $unionMemberType = $types->[$i];
5735 my $unionMemberNumber = $i + 1;
5736 my $unionMemberVariable = $nativeValue . $i;
5737 my $unionMemberEnabledVariable = $nativeValue . $i . "Enabled";
5738 my $unionMemberNativeValue = $unionMemberVariable;
5739 $unionMemberNativeValue .= ".release()" if (IsRefPtrType($unionMemberType));
5740 my $returnJSValueCode = NativeToJSValue($unionMemberType, $extendedAttributes, $unionMemberNativeValue, $indent . " ", $receiver, $getIsolate, $getCallbackInfo, $getScriptWrappable, $forMainWorldSuffix, $returnValueArg);
5742 if ($isReturnValue) {
5743 $code .= "${indent}if (${unionMemberEnabledVariable}) {\n";
5744 $code .= "${returnJSValueCode}\n";
5745 $code .= "${indent} return;\n";
5746 $code .= "${indent}}";
5748 $code .= "${indent}if (${unionMemberEnabledVariable})\n";
5749 $code .= "${returnJSValueCode}";
5753 if ($isReturnValue) {
5754 # Fall back to returning null if none of the union members results are returned.
5755 push @codes, "${indent}v8SetReturnValueNull(${getCallbackInfo});";
5757 return join "\n", @codes;
5760 if ($type eq "boolean") {
5761 return "${indent}v8SetReturnValueBool(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
5762 return "$indent$receiver v8Boolean($nativeValue, $getIsolate);";
5765 if ($type eq "void") { # equivalent to v8Undefined()
5766 return "" if $isReturnValue;
5767 return "$indent$receiver v8Undefined();"
5770 # HTML5 says that unsigned reflected attributes should be in the range
5771 # [0, 2^31). When a value isn't in this range, a default value (or 0)
5772 # should be returned instead.
5773 if ($extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
5774 $nativeValue =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
5775 return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, std::max(0, ${nativeValue}));" if $isReturnValue;
5776 return "$indent$receiver v8::Integer::NewFromUnsigned($getIsolate, std::max(0, " . $nativeValue . "));";
5779 my $nativeType = GetNativeType($type);
5780 if ($nativeType eq "int") {
5781 return "${indent}v8SetReturnValueInt(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
5782 return "$indent$receiver v8::Integer::New($getIsolate, $nativeValue);";
5785 if ($nativeType eq "unsigned") {
5786 return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
5787 return "$indent$receiver v8::Integer::NewFromUnsigned($getIsolate, $nativeValue);";
5790 if ($type eq "Date") {
5791 return "${indent}v8SetReturnValue(${getCallbackInfo}, v8DateOrNull($nativeValue, $getIsolate));" if $isReturnValue;
5792 return "$indent$receiver v8DateOrNull($nativeValue, $getIsolate);"
5795 # long long and unsigned long long are not representable in ECMAScript.
5796 if ($type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTimeStamp") {
5797 return "${indent}v8SetReturnValue(${getCallbackInfo}, static_cast<double>($nativeValue));" if $isReturnValue;
5798 return "$indent$receiver v8::Number::New($getIsolate, static_cast<double>($nativeValue));";
5801 if ($type eq "DOMString" && $extendedAttributes->{"ReflectOnly"}) {
5802 my $code = "${indent}String resultValue = ${nativeValue};\n";
5803 $code .= GenerateReflectOnlyCheck($extendedAttributes, ${indent});
5804 return "${code}${indent}v8SetReturnValueString(${getCallbackInfo}, resultValue, $getIsolate);" if $isReturnValue;
5805 return "${code}$indent$receiver resultValue";
5808 my $conv = $extendedAttributes->{"TreatReturnedNullStringAs"};
5809 if (($type eq "DOMString" || IsEnumType($type)) && $isReturnValue) {
5810 my $functionSuffix = "";
5811 if (defined $conv) {
5812 if ($conv eq "Null") {
5813 $functionSuffix = "OrNull";
5814 } elsif ($conv eq "Undefined") {
5815 $functionSuffix = "OrUndefined";
5817 die "Unknown value for TreatReturnedNullStringAs extended attribute";
5820 return "${indent}v8SetReturnValueString${functionSuffix}(${getCallbackInfo}, $nativeValue, $getIsolate);";
5823 if ($type eq "DOMString" or IsEnumType($type)) {
5824 my $returnValue = "";
5825 if (defined $conv) {
5826 if ($conv eq "Null") {
5827 $returnValue = "v8StringOrNull($nativeValue, $getIsolate)";
5828 } elsif ($conv eq "Undefined") {
5829 $returnValue = "v8StringOrUndefined($nativeValue, $getIsolate)";
5831 die "Unknown value for TreatReturnedNullStringAs extended attribute";
5834 $returnValue = "v8String($getIsolate, $nativeValue)";
5836 return "$indent$receiver $returnValue;";
5839 if (IsPrimitiveType($type)) {
5840 die "unexpected type $type" if not ($type eq "float" or $type eq "double");
5841 return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
5842 return "$indent$receiver v8::Number::New($getIsolate, $nativeValue);";
5845 if ($nativeType eq "ScriptValue" or $nativeType eq "ScriptPromise") {
5846 return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue}.v8Value());" if $isReturnValue;
5847 return "$indent$receiver $nativeValue.v8Value();";
5850 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5852 if ($arrayOrSequenceType) {
5853 if (IsRefPtrType($arrayOrSequenceType)) {
5854 AddIncludesForType($arrayOrSequenceType);
5856 return "${indent}v8SetReturnValue(${getCallbackInfo}, v8Array($nativeValue, $getIsolate));" if $isReturnValue;
5857 return "$indent$receiver v8Array($nativeValue, $getIsolate);";
5860 AddIncludesForType($type);
5862 if ($type eq "SerializedScriptValue") {
5863 my $returnValue = "$nativeValue ? $nativeValue->deserialize() : v8::Handle<v8::Value>(v8::Null($getIsolate))";
5864 return "${indent}v8SetReturnValue(${getCallbackInfo}, $returnValue);" if $isReturnValue;
5865 return "$indent$receiver $returnValue;";
5868 if ($getScriptWrappable) {
5869 # FIXME: Use safe handles
5870 if ($isReturnValue) {
5871 if ($forMainWorldSuffix eq "ForMainWorld") {
5872 return "${indent}v8SetReturnValueForMainWorld(${getCallbackInfo}, $nativeValue);";
5874 return "${indent}v8SetReturnValueFast(${getCallbackInfo}, $nativeValue, $getScriptWrappable);";
5877 # FIXME: Use safe handles
5878 return "${indent}v8SetReturnValue(${getCallbackInfo}, $nativeValue);" if $isReturnValue;
5879 return "$indent$receiver toV8($nativeValue, $creationContext, $getIsolate);";
5885 my $interface = shift;
5886 my $outputDirectory = shift;
5888 my $name = $interface->name;
5889 my $headerFileName = "$outputDirectory/V8$name.h";
5890 my $implFileName = "$outputDirectory/V8$name.cpp";
5893 foreach my $include (keys %implIncludes) {
5894 push @includes, "\"$include\"";
5897 #FIXME: do not treat main header special
5898 my $mainInclude = "\"V8$name.h\"";
5899 foreach my $include (sort @includes) {
5900 $implementation{includes}->add("#include $include\n") unless $include eq $mainInclude;
5902 $implementation{includes}->add("\n") unless $interface->isCallback;
5903 WriteFileIfChanged($implFileName, $implementation{root}->toString());
5907 WriteFileIfChanged($headerFileName, $header{root}->toString());
5910 sub ConvertToV8StringResource
5912 my $attributeOrParameter = shift;
5913 my $nativeType = shift;
5914 my $variableName = shift;
5917 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/;
5918 if ($attributeOrParameter->type eq "DOMString" or IsEnumType($attributeOrParameter->type)) {
5919 return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $value);"
5921 return "$nativeType $variableName($value, true);";
5925 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
5926 sub GetRuntimeEnabledFunctionName
5928 my $signature = shift;
5930 # Given [RuntimeEnabled=FeatureName],
5931 # return RuntimeEnabledFeatures::{featureName}Enabled;
5932 my $featureName = ToMethodName($signature->extendedAttributes->{"RuntimeEnabled"});
5933 return "RuntimeEnabledFeatures::${featureName}Enabled";
5936 sub GetContextEnabledFunctionName
5938 my $signature = shift;
5940 # Given [PerContextEnabled=FeatureName],
5941 # return ContextFeatures::{featureName}Enabled
5942 my $featureName = ToMethodName($signature->extendedAttributes->{"PerContextEnabled"});
5943 return "ContextFeatures::${featureName}Enabled";
5946 sub GetPassRefPtrType
5948 my $interface = shift;
5949 my $nativeType = GetNativeTypeForConversions($interface);
5951 my $willBe = IsWillBeGarbageCollectedType($interface->name) ? "WillBeRawPtr" : "";
5952 my $extraSpace = $nativeType =~ />$/ ? " " : "";
5953 return "PassRefPtr${willBe}<${nativeType}${extraSpace}>";
5956 sub WriteFileIfChanged
5958 my $fileName = shift;
5959 my $contents = shift;
5961 if (-f $fileName && $writeFileOnlyIfChanged) {
5962 open FH, "<", $fileName or die "Couldn't open $fileName: $!\n";
5964 my $oldContents = join "", @lines;
5966 return if $contents eq $oldContents;
5968 open FH, ">", $fileName or die "Couldn't open $fileName: $!\n";
5975 my $interface = shift;
5976 my $beforeRecursion = shift;
5977 my $afterRecursion = shift;
5981 my $currentInterface = shift;
5983 if ($currentInterface->parent) {
5984 my $parentInterface = ParseInterface($currentInterface->parent);
5985 if ($beforeRecursion) {
5986 &$beforeRecursion($parentInterface) eq 'prune' and return;
5988 &$recurse($parentInterface);
5989 &$afterRecursion($parentInterface) if $afterRecursion;
5993 &$recurse($interface);
6000 return 1 if $integerTypeHash{$type};
6001 return 1 if $primitiveTypeHash{$type};
6009 return 1 if $integerTypeHash{$type};
6013 sub IsCallbackFunctionType
6017 return 1 if $callbackFunctionTypeHash{$type};
6025 return 1 if $enumTypeHash{$type};
6033 return @{$enumTypeHash{$type}};
6036 sub IsSVGTypeNeedingTearOff
6040 return 1 if $svgTypeNeedingTearOff{$type};
6044 sub IsSVGTypeWithWritablePropertiesNeedingTearOff
6048 return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type};
6052 sub IsTypedArrayType
6055 return 1 if $typedArrayHash{$type};
6059 sub IsWillBeGarbageCollectedType
6061 my $interfaceName = shift;
6062 return 0 unless IsWrapperType($interfaceName);
6063 my $interface = ParseInterface($interfaceName);
6064 return $interface->extendedAttributes->{"WillBeGarbageCollected"};
6071 return 0 if $type eq "any";
6072 return 0 if IsPrimitiveType($type);
6073 return 0 if GetArrayType($type);
6074 return 0 if GetSequenceType($type);
6075 return 0 if $type eq "Promise";
6076 return 0 if IsCallbackFunctionType($type);
6077 return 0 if IsEnumType($type);
6078 return 0 if IsUnionType($type);
6079 return 0 if $type eq "Dictionary";
6084 sub IsNullableParameter
6086 my $parameter = shift;
6088 return $parameter->isNullable && !IsRefPtrType($parameter->type) && $parameter->type ne "Dictionary";
6091 sub GetSVGTypeNeedingTearOff
6095 return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type};
6099 sub GetSVGWrappedTypeNeedingTearOff
6103 my $svgTypeNeedingTearOff = GetSVGTypeNeedingTearOff($type);
6104 return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff;
6106 if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) {
6107 $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//;
6108 } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) {
6109 $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//;
6110 } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) {
6111 $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//;
6112 } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) {
6113 $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//;
6114 } elsif ($svgTypeNeedingTearOff =~ /SVGMatrixTearOff/) {
6115 $svgTypeNeedingTearOff = 'SVGMatrix';
6118 $svgTypeNeedingTearOff =~ s/>//;
6119 return $svgTypeNeedingTearOff;
6122 sub IsSVGAnimatedType
6126 return 0 if $svgTypeNewPropertyImplementation{$type};
6128 return $type =~ /^SVGAnimated/;
6131 sub SVGTypeNeedsToHoldContextElement
6135 return IsSVGTypeNeedingTearOff($type) || IsSVGAnimatedType($type);
6142 return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/;
6150 return $1 if $type =~ /^([\w\d_\s]+)\[\]/;
6154 sub GetArrayOrSequenceType
6158 return GetArrayType($type) || GetSequenceType($type);
6161 sub AssertNotSequenceType
6164 die "Sequences must not be used as the type of an attribute, constant or exception field." if GetSequenceType($type);
6167 sub FirstLetterToUpperCase
6170 my $ret = ucfirst($param);
6171 # Capitalize initial acronym, e.g., xml -> setXML
6172 $ret =~ s/Xml/XML/ if $ret =~ /^Xml/;
6173 $ret =~ s/Css/CSS/ if $ret =~ /^Css/;
6174 $ret =~ s/Html/HTML/ if $ret =~ /^Html/;
6175 $ret =~ s/Ime/IME/ if $ret =~ /^Ime/;
6176 $ret =~ s/Svg/SVG/ if $ret =~ /^Svg/;
6180 # URL becomes url, but SetURL becomes setURL.
6184 my $ret = lcfirst($param);
6185 $ret =~ s/hTML/html/ if $ret =~ /^hTML/;
6186 $ret =~ s/iME/ime/ if $ret =~ /^iME/;
6187 $ret =~ s/uRL/url/ if $ret =~ /^uRL/;
6188 $ret =~ s/jS/js/ if $ret =~ /^jS/;
6189 $ret =~ s/xML/xml/ if $ret =~ /^xML/;
6190 $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/;
6191 $ret =~ s/cSS/css/ if $ret =~ /^cSS/;
6193 # For HTML5 FileSystem API Flags attributes.
6194 # (create is widely used to instantiate an object and must be avoided.)
6195 $ret =~ s/^create/isCreate/ if $ret =~ /^create$/;
6196 $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/;
6201 sub NamespaceForAttributeName
6203 my ($interfaceName, $attributeName) = @_;
6204 return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$attributeName};
6208 # Identifies overloaded functions and for each function adds an array with
6209 # links to its respective overloads (including itself).
6210 sub LinkOverloadedFunctions
6212 my $interface = shift;
6214 my %nameToFunctionsMap = ();
6215 foreach my $function (@{$interface->functions}) {
6216 my $name = $function->name;
6217 $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name} or !$name; # Nameless functions cannot be overloaded
6218 push(@{$nameToFunctionsMap{$name}}, $function);
6219 $function->{overloads} = $nameToFunctionsMap{$name};
6220 $function->{overloadIndex} = @{$nameToFunctionsMap{$name}};
6224 sub AttributeNameForGetterAndSetter
6226 my $attribute = shift;
6228 my $attributeName = GetImplName($attribute);
6229 if ($attribute->extendedAttributes->{"ImplementedAs"}) {
6230 $attributeName = $attribute->extendedAttributes->{"ImplementedAs"};
6232 my $attributeType = $attribute->type;
6234 return $attributeName;
6237 sub ContentAttributeName
6239 my ($interfaceName, $attribute) = @_;
6241 my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"};
6242 return undef if !$contentAttributeName;
6244 $contentAttributeName = lc AttributeNameForGetterAndSetter($attribute) if $contentAttributeName eq "VALUE_IS_MISSING";
6246 my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeName);
6248 AddToImplIncludes("${namespace}.h");
6249 # Attr (not Attribute) used in core content attributes
6250 return "${namespace}::${contentAttributeName}Attr";
6253 sub GetterExpression
6255 my ($interfaceName, $attribute) = @_;
6257 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute);
6259 if (!$contentAttributeName) {
6260 return (ToMethodName(AttributeNameForGetterAndSetter($attribute)));
6264 if ($attribute->extendedAttributes->{"URL"}) {
6265 $functionName = "getURLAttribute";
6266 } elsif ($attribute->type eq "boolean") {
6267 $functionName = "fastHasAttribute";
6268 } elsif ($attribute->type eq "long") {
6269 $functionName = "getIntegralAttribute";
6270 } elsif ($attribute->type eq "unsigned long") {
6271 $functionName = "getUnsignedIntegralAttribute";
6273 if ($contentAttributeName eq "HTMLNames::idAttr") {
6274 $functionName = "getIdAttribute";
6275 $contentAttributeName = "";
6276 } elsif ($contentAttributeName eq "HTMLNames::nameAttr") {
6277 $functionName = "getNameAttribute";
6278 $contentAttributeName = "";
6279 } elsif ($contentAttributeName eq "HTMLNames::classAttr") {
6280 $functionName = "getClassAttribute";
6281 $contentAttributeName = "";
6283 # We cannot use fast attributes for animated SVG types.
6284 $functionName = IsSVGAnimatedType($attribute->type) ? "getAttribute" : "fastGetAttribute";
6288 return ($functionName, $contentAttributeName);
6291 sub SetterExpression
6293 my ($interfaceName, $attribute) = @_;
6295 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute);
6297 if (!$contentAttributeName) {
6298 return ("set" . FirstLetterToUpperCase(AttributeNameForGetterAndSetter($attribute)));
6302 if ($attribute->type eq "boolean") {
6303 $functionName = "setBooleanAttribute";
6304 } elsif ($attribute->type eq "long") {
6305 $functionName = "setIntegralAttribute";
6306 } elsif ($attribute->type eq "unsigned long") {
6307 $functionName = "setUnsignedIntegralAttribute";
6309 $functionName = "setAttribute";
6312 return ($functionName, $contentAttributeName);
6315 sub GenerateConditionalString
6319 my $conditional = $node->extendedAttributes->{"Conditional"};
6321 return GenerateConditionalStringFromAttributeValue($conditional);
6327 sub GenerateConditionalStringFromAttributeValue
6329 my $conditional = shift;
6331 my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : ''));
6333 # Avoid duplicated conditions.
6335 map { $conditions{$_} = 1 } split('\\' . $operator, $conditional);
6336 return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %conditions) . ")";
6338 return "ENABLE(" . $conditional . ")";
6342 sub GenerateCompileTimeCheckForEnumsIfNeeded
6344 my $interface = shift;
6345 my $implClassName = GetImplName($interface);
6347 # If necessary, check that all constants are available as enums with the same value.
6348 if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface->constants}) {
6349 foreach my $constant (@{$interface->constants}) {
6350 my $reflect = $constant->extendedAttributes->{"Reflect"};
6351 my $name = $reflect ? $reflect : $constant->name;
6352 my $value = $constant->value;
6354 if ($constant->extendedAttributes->{"ImplementedBy"}) {
6355 my $implementedByImplName = GetImplNameFromImplementedBy($constant->extendedAttributes->{"ImplementedBy"});
6356 push(@checks, " COMPILE_ASSERT($value == " . $implementedByImplName . "::$name, TheValueOf${implClassName}_${name}DoesntMatchWithImplementation);\n");
6358 push(@checks, " COMPILE_ASSERT($value == ${implClassName}::$name, TheValueOf${implClassName}_${name}DoesntMatchWithImplementation);\n");
6365 sub GenerateReflectOnlyCheck
6367 my $extendedAttributes = shift;
6370 my $attributeValueList = $extendedAttributes->{"ReflectOnly"};
6371 my @knownValues = split(quotemeta("|"), $attributeValueList);
6373 my $missingValueDefault = $extendedAttributes->{"ReflectMissing"};
6374 if ($missingValueDefault) {
6375 if (!grep { $_ eq $missingValueDefault } @knownValues) {
6376 die "The [ReflectMissing] attribute value '${missingValueDefault}' is not a known value ";
6378 $missingValueDefault = "resultValue = \"${missingValueDefault}\"";
6380 $missingValueDefault = "";
6383 my $invalidValueDefault = $extendedAttributes->{"ReflectInvalid"};
6384 if ($invalidValueDefault) {
6385 if (!grep { $_ eq $invalidValueDefault } @knownValues) {
6386 die "The [ReflectInvalid] attribute value '${invalidValueDefault}' is not a known value ";
6388 $invalidValueDefault = "resultValue = \"${invalidValueDefault}\"";
6390 $invalidValueDefault = "resultValue = \"\"";
6393 my @normalizeAttributeCode = ();
6395 # Attributes without a value (div empty-attribute>) can be
6396 # separately reflected to some value.
6398 my $isAttributeValueMissing = "resultValue.isEmpty()";
6399 my $emptyValueDefault = $extendedAttributes->{"ReflectEmpty"};
6400 if ($emptyValueDefault) {
6401 if (!grep { $_ eq $emptyValueDefault } @knownValues) {
6402 die "The [ReflectEmpty] attribute value '${emptyValueDefault}' is not a known value ";
6404 $isAttributeValueMissing = "resultValue.isNull()";
6405 push(@normalizeAttributeCode, "${indent}} else if (resultValue.isEmpty()) {");
6406 push(@normalizeAttributeCode, "${indent} resultValue = \"$emptyValueDefault\";");
6409 # Attribute is limited to only known values: check that the attribute
6410 # value is one of those..and if not, set it to the empty string.
6411 # ( http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values )
6413 foreach my $knownValue (@knownValues) {
6414 push(@normalizeAttributeCode, "${indent}} else if (equalIgnoringCase(resultValue, \"$knownValue\")) {");
6415 push(@normalizeAttributeCode, "${indent} resultValue = \"$knownValue\";");
6417 my $normalizeAttributeValue = join("\n", @normalizeAttributeCode);
6419 ${indent}if ($isAttributeValueMissing) {
6420 ${indent} $missingValueDefault;
6421 ${normalizeAttributeValue}
6423 ${indent} $invalidValueDefault;
6429 sub ExtendedAttributeContains
6431 my $extendedAttributeValue = shift;
6432 return 0 unless $extendedAttributeValue;
6433 my $keyword = shift;
6435 my @extendedAttributeValues = split /\s*(\&|\|)\s*/, $extendedAttributeValue;
6436 return grep { $_ eq $keyword } @extendedAttributeValues;
6439 sub InheritsInterface
6441 my $interface = shift;
6442 my $interfaceName = shift;
6445 return 1 if $interfaceName eq $interface->name;
6446 ForAllParents($interface, sub {
6447 my $currentInterface = shift;
6448 if ($currentInterface->name eq $interfaceName) {
6457 sub InheritsExtendedAttribute
6459 my $interface = shift;
6460 my $extendedAttribute = shift;
6463 return 1 if $interface->extendedAttributes->{$extendedAttribute};
6464 ForAllParents($interface, sub {
6465 my $currentInterface = shift;
6466 if ($currentInterface->extendedAttributes->{$extendedAttribute}) {
6475 sub NeedsSpecialWrap
6477 my $interface = shift;
6479 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "ToV8");
6480 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "Wrap");
6481 return 1 if $interface->extendedAttributes->{"SpecialWrapFor"};
6482 return 1 if InheritsInterface($interface, "Document");
6487 sub HasExceptionRaisingParameter
6489 my $function = shift;
6491 foreach my $parameter (@{$function->parameters}) {
6492 if ($parameter->type eq "SerializedScriptValue") {
6494 } elsif (IsIntegerType($parameter->type)) {