Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: Source/bindings/scripts/code_generator_v8.pm

Issue 181513006: IDL compiler: delete Perl compiler, remove unstable/ directory (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
12 #
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.
17 #
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.
22 #
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.
27 #
28
29 package Block;
30
31 # Sample code:
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();
38 #
39 # Output code:
40 # namespace Foo {
41 # void foo() {}
42 # namespace Bar {
43 # void bar() {}
44 # } // namespace Bar
45 # } // namespace Foo
46
47 sub new
48 {
49 my $package = shift;
50 my $name = shift || "Anonymous block";
51 my $header = shift || "";
52 my $footer = shift || "";
53
54 my $object = {
55 "name" => $name,
56 "header" => [$header],
57 "footer" => [$footer],
58 "contents" => [],
59 };
60 bless $object, $package;
61 return $object;
62 }
63
64 sub addHeader
65 {
66 my $object = shift;
67 my $header = shift || "";
68
69 push(@{$object->{header}}, $header);
70 }
71
72 sub addFooter
73 {
74 my $object = shift;
75 my $footer = shift || "";
76
77 push(@{$object->{footer}}, $footer);
78 }
79
80 sub add
81 {
82 my $object = shift;
83 my $content = shift || "";
84
85 push(@{$object->{contents}}, $content);
86 }
87
88 sub toString
89 {
90 my $object = shift;
91
92 my $header = join "", @{$object->{header}};
93 my $footer = join "", @{$object->{footer}};
94 my $code = "";
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();
100 } else {
101 $code .= $content;
102 }
103 }
104 $code .= $footer . "\n" if $footer;
105 $code .= "/* END " . $object->{name} . " */\n" if $verbose;
106 return $code;
107 }
108
109
110 package code_generator_v8;
111
112 use strict;
113 use Cwd;
114 use File::Basename;
115 use File::Find;
116 use File::Spec;
117
118 my $idlDocument;
119 my $idlDirectories;
120 my $preprocessor;
121 my $verbose;
122 my $interfaceIdlFiles;
123 my $writeFileOnlyIfChanged;
124 my $sourceRoot;
125
126 # Cache of IDL file pathnames.
127 my $idlFiles;
128 my $cachedInterfaces = {};
129
130 my %implIncludes = ();
131 my %headerIncludes = ();
132
133 # Header code structure:
134 # Root ... Copyright, include duplication check
135 # Conditional ... #if FEATURE ... #endif (to be removed soon)
136 # Includes
137 # NameSpaceWebCore
138 # Class
139 # ClassPublic
140 # ClassPrivate
141 my %header;
142
143 # Implementation code structure:
144 # Root ... Copyright
145 # Conditional ... #if FEATURE ... #endif (to be removed soon)
146 # Includes
147 # NameSpaceWebCore
148 # NameSpaceInternal ... namespace ${implClassName}V8Internal in case of no n-callback
149 my %implementation;
150
151 # The integer primitive types, a map from an IDL integer type to its
152 # binding-level type name.
153 #
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",
158 "octet" => "UInt8",
159 "short" => "Int16",
160 "long" => "Int32",
161 "long long" => "Int64",
162 "unsigned short" => "UInt16",
163 "unsigned long" => "UInt32",
164 "unsigned long long" => "UInt64"
165 );
166
167 # Other primitive types
168 #
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,
174 "DOMString" => 1,
175 "DOMTimeStamp" => 1, # typedef unsigned long long
176 "boolean" => 1,
177 "void" => 1,
178 "float" => 1,
179 "double" => 1,
180 );
181
182 my %nonWrapperTypes = ("CompareHow" => 1,
183 "Dictionary" => 1,
184 "EventHandler" => 1,
185 "EventListener" => 1,
186 "MediaQueryListListener" => 1,
187 "NodeFilter" => 1,
188 "SerializedScriptValue" => 1,
189 "any" => 1,
190 );
191
192 my %typedArrayHash = ("ArrayBuffer" => [],
193 "ArrayBufferView" => [],
194 "Uint8Array" => ["unsigned char", "v8::kExternalUnsignedBy teArray"],
195 "Uint8ClampedArray" => ["unsigned char", "v8::kExternalPix elArray"],
196 "Uint16Array" => ["unsigned short", "v8::kExternalUnsigned ShortArray"],
197 "Uint32Array" => ["unsigned int", "v8::kExternalUnsignedIn tArray"],
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"],
203 );
204
205 my %domNodeTypes = ("Attr" => 1,
206 "CDATASection" => 1,
207 "CharacterData" => 1,
208 "Comment" => 1,
209 "Document" => 1,
210 "DocumentFragment" => 1,
211 "DocumentType" => 1,
212 "Element" => 1,
213 "Entity" => 1,
214 "HTMLDocument" => 1,
215 "Node" => 1,
216 "Notation" => 1,
217 "ProcessingInstruction" => 1,
218 "ShadowRoot" => 1,
219 "Text" => 1,
220 "TestNode" => 1,
221 "TestInterfaceDocument" => 1,
222 "TestInterfaceNode" => 1,
223 "XMLDocument" => 1,
224 );
225
226 my %callbackFunctionTypeHash = ();
227
228 my %enumTypeHash = ();
229
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, "onmouseov er" => 1,
234 "onmouseup" => 1, "onresize" => 1, "onscroll" => 1,
235 "onunload" => 1);
236
237 my %svgTypeNewPropertyImplementation = (
238 "SVGAngle" => 1,
239 "SVGLength" => 1,
240 "SVGLengthList" => 1,
241 "SVGNumber" => 1,
242 "SVGNumberList" => 1,
243 "SVGPathSegList" => 1,
244 "SVGPoint" => 1,
245 "SVGPointList" => 1,
246 "SVGPreserveAspectRatio" => 1,
247 "SVGRect" => 1,
248 "SVGString" => 1,
249 "SVGStringList" => 1,
250 "SVGTransform" => 1,
251 "SVGTransformList" => 1,
252 );
253
254 my %svgTypeNeedingTearOff = (
255 );
256
257 my %svgTypeWithWritablePropertiesNeedingTearOff = (
258 );
259
260 # Default license header
261 my $licenseHeader = <<EOF;
262 /*
263 * Copyright (C) 2013 Google Inc. All rights reserved.
264 *
265 * Redistribution and use in source and binary forms, with or without
266 * modification, are permitted provided that the following conditions are
267 * met:
268 *
269 * * Redistributions of source code must retain the above copyright
270 * notice, this list of conditions and the following disclaimer.
271 * * Redistributions in binary form must reproduce the above
272 * copyright notice, this list of conditions and the following disclaimer
273 * in the documentation and/or other materials provided with the
274 * distribution.
275 * * Neither the name of Google Inc. nor the names of its
276 * contributors may be used to endorse or promote products derived from
277 * this software without specific prior written permission.
278 *
279 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
280 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
281 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
283 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
284 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
285 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
286 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
287 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
288 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
289 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
290 */
291
292 // This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY!
293
294 EOF
295
296 sub new
297 {
298 my $object = shift;
299 my $reference = { };
300
301 $idlDocument = shift;
302 $idlDirectories = shift;
303 $preprocessor = shift;
304 $verbose = shift;
305 $interfaceIdlFiles = shift;
306 $writeFileOnlyIfChanged = shift;
307
308 $sourceRoot = dirname(dirname(dirname(Cwd::abs_path($0))));
309
310 bless($reference, $object);
311 return $reference;
312 }
313
314
315 sub IDLFileForInterface
316 {
317 my $interfaceName = shift;
318
319 unless ($idlFiles) {
320 my @directories = map { $_ = "$sourceRoot/$_" if -d "$sourceRoot/$_"; $_ } @$idlDirectories;
321 push(@directories, ".");
322
323 $idlFiles = { };
324 foreach my $idlFile (@$interfaceIdlFiles) {
325 $idlFiles->{fileparse(basename($idlFile), ".idl")} = $idlFile;
326 }
327
328 my $wanted = sub {
329 $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/;
330 $File::Find::prune = 1 if /^\../;
331 };
332 find($wanted, @directories);
333 }
334
335 return $idlFiles->{$interfaceName};
336 }
337
338 sub ParseInterface
339 {
340 my $interfaceName = shift;
341
342 if (exists $cachedInterfaces->{$interfaceName}) {
343 return $cachedInterfaces->{$interfaceName};
344 }
345
346 # Step #1: Find the IDL file associated with 'interface'
347 my $filename = IDLFileForInterface($interfaceName)
348 or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n");
349
350 print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceN ame\"\n" if $verbose;
351
352 # Step #2: Parse the found IDL file (in quiet mode).
353 my $parser = idl_parser->new(1);
354 my $document = $parser->Parse($filename, $preprocessor);
355
356 foreach my $interface (@{$document->interfaces}) {
357 if ($interface->name eq $interfaceName or $interface->isPartial) {
358 $cachedInterfaces->{$interfaceName} = $interface;
359 return $interface;
360 }
361 }
362
363 die("Could NOT find interface definition for $interfaceName in $filename");
364 }
365
366 sub GenerateInterface
367 {
368 my $object = shift;
369 my $interface = shift;
370
371 %callbackFunctionTypeHash = map { $_->name => $_ } @{$idlDocument->callbackF unctions};
372 %enumTypeHash = map { $_->name => $_->values } @{$idlDocument->enumerations} ;
373 my $v8ClassName = GetV8ClassName($interface);
374 my $defineName = $v8ClassName . "_h";
375 my $internalNamespace = GetImplName($interface) . "V8Internal";
376
377 my $conditionalString = GenerateConditionalString($interface);
378 my $conditionalIf = "";
379 my $conditionalEndif = "";
380 if ($conditionalString) {
381 $conditionalIf = "#if ${conditionalString}";
382 $conditionalEndif = "#endif // ${conditionalString}";
383 }
384
385 $header{root} = new Block("ROOT", "", "");
386 # FIXME: newlines should be generated by Block::toString().
387 $header{conditional} = new Block("Conditional", "$conditionalIf", $condition alEndif ? "$conditionalEndif" : "");
388 $header{includes} = new Block("Includes", "", "");
389 $header{nameSpaceWebCore} = new Block("Namespace WebCore", "\nnamespace WebC ore {\n", "}");
390 $header{class} = new Block("Class definition", "", "");
391 $header{classPublic} = new Block("Class public:", "public:", "");
392 $header{classPrivate} = new Block("Class private:", "private:", "");
393
394 $header{root}->add($header{conditional});
395 $header{conditional}->add($header{includes});
396 $header{conditional}->add($header{nameSpaceWebCore});
397 $header{nameSpaceWebCore}->add($header{class});
398 $header{class}->add($header{classPublic});
399 $header{class}->add($header{classPrivate});
400
401 # - Add default header template
402 $header{root}->addHeader($licenseHeader);
403 $header{root}->addHeader("#ifndef $defineName\n#define $defineName\n");
404 $header{root}->addFooter("#endif // $defineName");
405
406 $implementation{root} = new Block("ROOT", "", "");
407 $implementation{conditional} = new Block("Conditional", $conditionalIf, $con ditionalEndif);
408 $implementation{includes} = new Block("Includes", "", "");
409
410 # FIXME: newlines should be generated by Block::toString().
411 my $nameSpaceWebCoreBegin = "namespace WebCore {\n";
412 my $nameSpaceWebCoreEnd = "} // namespace WebCore";
413 $nameSpaceWebCoreBegin = "$nameSpaceWebCoreBegin\n" unless $interface->isCal lback;
414 $nameSpaceWebCoreBegin = "\n$nameSpaceWebCoreBegin" if $interface->isCallbac k;
415 $implementation{nameSpaceWebCore} = new Block("Namespace WebCore", $nameSpac eWebCoreBegin, $nameSpaceWebCoreEnd);
416 $implementation{nameSpaceInternal} = new Block("Internal namespace", "namesp ace $internalNamespace {\n", "} // namespace $internalNamespace\n");
417
418 $implementation{root}->add($implementation{conditional});
419 $implementation{conditional}->add($implementation{includes});
420 $implementation{conditional}->add($implementation{nameSpaceWebCore});
421 if (!$interface->isCallback) {
422 $implementation{nameSpaceWebCore}->add($implementation{nameSpaceInternal });
423 }
424
425 # - Add default header template
426 $implementation{root}->addHeader($licenseHeader);
427 $implementation{root}->addHeader("#include \"config.h\"");
428 $implementation{includes}->add("#include \"${v8ClassName}.h\"\n\n");
429
430 # Start actual generation
431 if ($interface->isCallback) {
432 $object->GenerateCallbackHeader($interface);
433 $object->GenerateCallbackImplementation($interface);
434 } else {
435 $object->GenerateHeader($interface);
436 $object->GenerateImplementation($interface);
437 }
438 }
439
440 sub AddToImplIncludes
441 {
442 my $header = shift;
443 $implIncludes{$header} = 1;
444 }
445
446 sub AddToHeaderIncludes
447 {
448 my @includes = @_;
449
450 for my $include (@includes) {
451 $headerIncludes{$include} = 1;
452 }
453 }
454
455 sub AddIncludesForType
456 {
457 my $type = shift;
458
459 return if IsPrimitiveType($type) or IsEnumType($type) or $type eq "object";
460
461 $type = $1 if $type =~ /SVG\w+TearOff<(\w+)>/;
462
463 # Handle non-wrapper types explicitly
464 if ($type eq "any" || IsCallbackFunctionType($type)) {
465 AddToImplIncludes("bindings/v8/ScriptValue.h");
466 } elsif ($type eq "CompareHow") {
467 } elsif ($type eq "Dictionary") {
468 AddToImplIncludes("bindings/v8/Dictionary.h");
469 } elsif ($type eq "EventHandler") {
470 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h");
471 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
472 } elsif ($type eq "EventListener") {
473 AddToImplIncludes("bindings/v8/BindingSecurity.h");
474 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
475 AddToImplIncludes("core/frame/DOMWindow.h");
476 } elsif ($type eq "MediaQueryListListener") {
477 AddToImplIncludes("core/css/MediaQueryListListener.h");
478 } elsif ($type eq "Promise") {
479 AddToImplIncludes("bindings/v8/ScriptPromise.h");
480 } elsif ($type eq "SerializedScriptValue") {
481 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
482 } elsif (IsTypedArrayType($type)) {
483 AddToImplIncludes("bindings/v8/custom/V8${type}Custom.h");
484 } elsif (my $arrayType = GetArrayType($type)) {
485 AddIncludesForType($arrayType);
486 } elsif (my $sequenceType = GetSequenceType($type)) {
487 AddIncludesForType($sequenceType);
488 } elsif (IsUnionType($type)) {
489 for my $unionMemberType (@{$type->unionMemberTypes}) {
490 AddIncludesForType($unionMemberType);
491 }
492 } else {
493 AddToImplIncludes("V8${type}.h");
494 }
495 }
496
497 sub HeaderFilesForInterface
498 {
499 my $interfaceName = shift;
500 my $implClassName = shift;
501
502 my @includes = ();
503 if (IsPrimitiveType($interfaceName) or IsEnumType($interfaceName) or IsCallb ackFunctionType($interfaceName)) {
504 # Not interface type, no header files
505 } else {
506 my $idlFilename = Cwd::abs_path(IDLFileForInterface($interfaceName)) or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n");
507 my $idlRelPath = File::Spec->abs2rel($idlFilename, $sourceRoot);
508 push(@includes, dirname($idlRelPath) . "/" . $implClassName . ".h");
509 }
510 return @includes;
511 }
512
513 sub NeedsVisitDOMWrapper
514 {
515 my $interface = shift;
516 return ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "VisitDOMWrapper") || $interface->extendedAttributes->{"SetWrapperReferenceFrom "} || $interface->extendedAttributes->{"SetWrapperReferenceFromReference"} || $i nterface->extendedAttributes->{"SetWrapperReferenceTo"} || SVGTypeNeedsToHoldCon textElement($interface->name);
517 }
518
519 sub GenerateVisitDOMWrapper
520 {
521 my $interface = shift;
522 my $implClassName = GetImplName($interface);
523 my $v8ClassName = GetV8ClassName($interface);
524
525 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "V isitDOMWrapper")) {
526 return;
527 }
528
529 my $nativeType = GetNativeTypeForConversions($interface);
530 my $code = <<END;
531 void ${v8ClassName}::visitDOMWrapper(void* object, const v8::Persistent<v8::Obje ct>& wrapper, v8::Isolate* isolate)
532 {
533 ${nativeType}* impl = fromInternalPointer(object);
534 END
535 my $needSetWrapperReferenceContext = SVGTypeNeedsToHoldContextElement($inter face->name) || $interface->extendedAttributes->{"SetWrapperReferenceTo"};
536 if ($needSetWrapperReferenceContext) {
537 $code .= <<END;
538 v8::Local<v8::Object> creationContext = v8::Local<v8::Object>::New(isolate, wrapper);
539 V8WrapperInstantiationScope scope(creationContext, isolate);
540 END
541 }
542 for my $setReference (@{$interface->extendedAttributes->{"SetWrapperReferenc eTo"}}) {
543 my $setReferenceType = $setReference->type;
544 my $setReferenceV8Type = "V8".$setReferenceType;
545
546 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProp ertyTypes($setReferenceType);
547 if ($svgPropertyType) {
548 $setReferenceType = $svgNativeType;
549 }
550 my $setReferenceImplType = GetImplNameFromImplementedBy($setReferenceTyp e);
551
552 my $setReferenceName = $setReference->name;
553
554 AddIncludesForType($setReferenceType);
555 $code .= <<END;
556 ${setReferenceImplType}* ${setReferenceName} = impl->${setReferenceName}();
557 if (${setReferenceName}) {
558 if (!DOMDataStore::containsWrapper<${setReferenceV8Type}>(${setReference Name}, isolate))
559 wrap(${setReferenceName}, creationContext, isolate);
560 DOMDataStore::setWrapperReference<${setReferenceV8Type}>(wrapper, ${setR eferenceName}, isolate);
561 }
562 END
563 }
564
565 my $isReachableMethod = $interface->extendedAttributes->{"SetWrapperReferenc eFrom"};
566 my $isReachableReferenceMethod = $interface->extendedAttributes->{"SetWrappe rReferenceFromReference"};
567
568 if ($isReachableMethod || $isReachableReferenceMethod) {
569 AddToImplIncludes("bindings/v8/V8GCController.h");
570 AddToImplIncludes("core/dom/Element.h");
571 if ($isReachableMethod) {
572 $code .= <<END;
573 if (Node* owner = impl->${isReachableMethod}()) {
574 Node* root = V8GCController::opaqueRootForGC(owner, isolate);
575 isolate->SetReferenceFromGroup(v8::UniqueId(reinterpret_cast<intptr_t>(r oot)), wrapper);
576 return;
577 }
578 END
579 } else {
580 $code .= <<END;
581 Node* root = V8GCController::opaqueRootForGC(&impl->${isReachableReferenceMe thod}(), isolate);
582 isolate->SetReferenceFromGroup(v8::UniqueId(reinterpret_cast<intptr_t>(root) ), wrapper);
583 }
584
585 END
586 }
587 }
588
589 if (!$isReachableReferenceMethod) {
590 $code .= <<END;
591 setObjectGroup(object, wrapper, isolate);
592 }
593
594 END
595 }
596
597 $implementation{nameSpaceWebCore}->add($code);
598 }
599
600 sub GetSVGPropertyTypes
601 {
602 my $implType = shift;
603
604 my $svgPropertyType;
605 my $svgListPropertyType;
606 my $svgNativeType;
607
608 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $impl Type =~ /SVG/;
609
610 $svgNativeType = GetSVGTypeNeedingTearOff($implType);
611 return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgN ativeType;
612
613 # Append space to avoid compilation errors when using PassRefPtr<$svgNative Type>
614 $svgNativeType = "$svgNativeType ";
615
616 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($implType);
617 if ($svgNativeType =~ /SVGPropertyTearOff/) {
618 $svgPropertyType = $svgWrappedNativeType;
619 AddToHeaderIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h");
620 } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SV GStaticListPropertyTearOff/ or $svgNativeType =~ /SVGTransformListPropertyTearOf f/) {
621 $svgListPropertyType = $svgWrappedNativeType;
622 AddToHeaderIncludes("core/svg/properties/SVGAnimatedListPropertyTearOff. h");
623 }
624
625 return ($svgPropertyType, $svgListPropertyType, $svgNativeType);
626 }
627
628 sub GetIndexedGetterFunction
629 {
630 my $interface = shift;
631
632 return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned lon g", 1);
633 }
634
635 sub GetIndexedSetterFunction
636 {
637 my $interface = shift;
638
639 return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned lon g", 2);
640 }
641
642 sub GetIndexedDeleterFunction
643 {
644 my $interface = shift;
645
646 return GetSpecialAccessorFunctionForType($interface, "deleter", "unsigned lo ng", 1);
647 }
648
649 sub GetNamedGetterFunction
650 {
651 my $interface = shift;
652 return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1);
653 }
654
655 sub GetNamedSetterFunction
656 {
657 my $interface = shift;
658 return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString", 2);
659 }
660
661 sub GetNamedDeleterFunction
662 {
663 my $interface = shift;
664 return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString", 1);
665 }
666
667 sub GetSpecialAccessorFunctionForType
668 {
669 my $interface = shift;
670 my $special = shift;
671 my $firstParameterType = shift;
672 my $numberOfParameters = shift;
673
674 foreach my $function (@{$interface->functions}) {
675 my $specials = $function->specials;
676 my $specialExists = grep { $_ eq $special } @$specials;
677 my $parameters = $function->parameters;
678 if ($specialExists and scalar(@$parameters) == $numberOfParameters and $ parameters->[0]->type eq $firstParameterType) {
679 return $function;
680 }
681 }
682
683 return 0;
684 }
685
686 sub GetV8StringResourceMode
687 {
688 my $extendedAttributes = shift;
689
690 # Blink uses the non-standard identifier NullString instead of Web IDL
691 # standard EmptyString, in [TreatNullAs=NullString] and [TreatUndefinedAs=Nu llString],
692 # and does not support [TreatUndefinedAs=Null] or [TreatUndefinedAs=Missing]
693 # https://sites.google.com/a/chromium.org/dev/blink/webidl/blink-idl-extende d-attributes#TOC-TreatNullAs-a-p-TreatUndefinedAs-a-p-
694 my $mode = "";
695 if (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNu llAs"} eq "NullString") and ($extendedAttributes->{"TreatUndefinedAs"} and $exte ndedAttributes->{"TreatUndefinedAs"} eq "NullString")) {
696 $mode = "WithUndefinedOrNullCheck";
697 } elsif ($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"Tre atNullAs"} eq "NullString") {
698 $mode = "WithNullCheck";
699 }
700 return $mode;
701 }
702
703 sub GenerateHeader
704 {
705 my $object = shift;
706 my $interface = shift;
707
708 my $interfaceName = $interface->name;
709 my $implClassName = GetImplName($interface);
710 my $v8ClassName = GetV8ClassName($interface);
711
712 LinkOverloadedFunctions($interface);
713
714 # Ensure the IsDOMNodeType function is in sync.
715 die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMN odeType($interfaceName) != InheritsInterface($interface, "Node");
716
717 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty Types($interfaceName);
718
719 my $parentInterface = $interface->parent;
720 AddToHeaderIncludes("V8${parentInterface}.h") if $parentInterface;
721 AddToHeaderIncludes("bindings/v8/WrapperTypeInfo.h");
722 AddToHeaderIncludes("bindings/v8/V8Binding.h");
723 AddToHeaderIncludes("bindings/v8/V8DOMWrapper.h");
724 AddToHeaderIncludes("heap/Handle.h");
725 AddToHeaderIncludes(HeaderFilesForInterface($interfaceName, $implClassName)) ;
726 foreach my $headerInclude (sort keys(%headerIncludes)) {
727 $header{includes}->add("#include \"${headerInclude}\"\n");
728 }
729
730 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> clas s SVGPropertyTearOff;\n") if $svgPropertyType;
731 if ($svgNativeType) {
732 if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) {
733 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyTy pe> class SVGStaticListPropertyTearOff;\n");
734 } else {
735 $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyTy pe> class SVGListPropertyTearOff;\n");
736 }
737 }
738
739 $header{nameSpaceWebCore}->addHeader("\nclass Dictionary;") if $interface->e xtendedAttributes->{"EventConstructor"};
740
741 my $nativeType = GetNativeTypeForConversions($interface);
742 if ($interface->extendedAttributes->{"NamedConstructor"}) {
743 $header{nameSpaceWebCore}->addHeader(<<END);
744
745 class V8${nativeType}Constructor {
746 public:
747 static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWor ldType);
748 static const WrapperTypeInfo wrapperTypeInfo;
749 };
750 END
751 }
752
753 $header{class}->addHeader("class $v8ClassName {");
754 $header{class}->addFooter("};");
755
756 $header{classPublic}->add(<<END);
757 static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*);
758 static v8::Handle<v8::Object> findInstanceInPrototypeChain(v8::Handle<v8::Va lue>, v8::Isolate*);
759 static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWor ldType);
760 static ${nativeType}* toNative(v8::Handle<v8::Object> object)
761 {
762 return fromInternalPointer(object->GetAlignedPointerFromInternalField(v8 DOMWrapperObjectIndex));
763 }
764 static ${nativeType}* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Val ue>);
765 static const WrapperTypeInfo wrapperTypeInfo;
766 END
767
768 $header{classPublic}->add(" static void derefObject(void*);\n");
769
770 if (NeedsVisitDOMWrapper($interface)) {
771 $header{classPublic}->add(" static void visitDOMWrapper(void*, const v8::Persistent<v8::Object>&, v8::Isolate*);\n");
772 }
773
774 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
775 $header{classPublic}->add(" static ActiveDOMObject* toActiveDOMObject (v8::Handle<v8::Object>);\n");
776 }
777
778 if (InheritsInterface($interface, "EventTarget")) {
779 $header{classPublic}->add(" static EventTarget* toEventTarget(v8::Han dle<v8::Object>);\n");
780 }
781
782 if ($interfaceName eq "Window") {
783 $header{classPublic}->add(<<END);
784 static v8::Handle<v8::ObjectTemplate> getShadowObjectTemplate(v8::Isolate*, WrapperWorldType);
785 END
786 }
787
788 my @perContextEnabledFunctions;
789 foreach my $function (@{$interface->functions}) {
790 my $name = $function->name;
791 next if $name eq "";
792 my $attrExt = $function->extendedAttributes;
793
794 if (HasCustomMethod($attrExt) && $function->{overloadIndex} == 1) {
795 my $conditionalString = GenerateConditionalString($function);
796 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio nalString;
797 $header{classPublic}->add(<<END);
798 static void ${name}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&);
799 END
800 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co nditionalString;
801 }
802 if ($attrExt->{"PerContextEnabled"}) {
803 push(@perContextEnabledFunctions, $function);
804 }
805 }
806
807 if (IsConstructable($interface)) {
808 $header{classPublic}->add(" static void constructorCallback(const v8: :FunctionCallbackInfo<v8::Value>&);\n");
809 END
810 }
811 if (HasCustomConstructor($interface)) {
812 $header{classPublic}->add(" static void constructorCustom(const v8::F unctionCallbackInfo<v8::Value>&);\n");
813 }
814
815 my @perContextEnabledAttributes;
816 foreach my $attribute (@{$interface->attributes}) {
817 my $name = $attribute->name;
818 my $attrExt = $attribute->extendedAttributes;
819 my $conditionalString = GenerateConditionalString($attribute);
820 if (HasCustomGetter($attrExt) && !$attrExt->{"ImplementedBy"}) {
821 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio nalString;
822 $header{classPublic}->add(<<END);
823 static void ${name}AttributeGetterCustom(const v8::PropertyCallbackInfo<v8:: Value>&);
824 END
825 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co nditionalString;
826 }
827 if (HasCustomSetter($attribute) && !$attrExt->{"ImplementedBy"}) {
828 $header{classPublic}->add("#if ${conditionalString}\n") if $conditio nalString;
829 $header{classPublic}->add(<<END);
830 static void ${name}AttributeSetterCustom(v8::Local<v8::Value>, const v8::Pro pertyCallbackInfo<void>&);
831 END
832 $header{classPublic}->add("#endif // ${conditionalString}\n") if $co nditionalString;
833 }
834 if ($attrExt->{"PerContextEnabled"}) {
835 push(@perContextEnabledAttributes, $attribute);
836 }
837 }
838
839 GenerateHeaderNamedAndIndexedPropertyAccessors($interface);
840 GenerateHeaderLegacyCallAsFunction($interface);
841 GenerateHeaderCustomInternalFieldIndices($interface);
842
843 my $toWrappedType;
844 my $fromWrappedType;
845 if ($interface->parent) {
846 my $v8ParentClassName = "V8" . $interface->parent;
847 $toWrappedType = "${v8ParentClassName}::toInternalPointer(impl)";
848 $fromWrappedType = "static_cast<${nativeType}*>(${v8ParentClassName}::fr omInternalPointer(object))";
849 } else {
850 $toWrappedType = "impl";
851 $fromWrappedType = "static_cast<${nativeType}*>(object)";
852 }
853
854 $header{classPublic}->add(<<END);
855 static inline void* toInternalPointer(${nativeType}* impl)
856 {
857 return $toWrappedType;
858 }
859
860 static inline ${nativeType}* fromInternalPointer(void* object)
861 {
862 return $fromWrappedType;
863 }
864 END
865
866 if ($interface->name eq "Window") {
867 $header{classPublic}->add(<<END);
868 static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v 8::Value> key, v8::AccessType, v8::Local<v8::Value> data);
869 static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data);
870 END
871 }
872
873 if (@perContextEnabledAttributes) {
874 $header{classPublic}->add(<<END);
875 static void installPerContextEnabledProperties(v8::Handle<v8::Object>, ${nat iveType}*, v8::Isolate*);
876 END
877 } else {
878 $header{classPublic}->add(<<END);
879 static void installPerContextEnabledProperties(v8::Handle<v8::Object>, ${nat iveType}*, v8::Isolate*) { }
880 END
881 }
882
883 if (@perContextEnabledFunctions) {
884 $header{classPublic}->add(<<END);
885 static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isol ate*);
886 END
887 } else {
888 $header{classPublic}->add(<<END);
889 static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isol ate*) { }
890 END
891 }
892
893 if ($interfaceName eq "HTMLElement") {
894 $header{classPublic}->add(<<END);
895 friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v 8::Object> creationContext, v8::Isolate*);
896 friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Ha ndle<v8::Object> creationContext, v8::Isolate*);
897 END
898 } elsif ($interfaceName eq "SVGElement") {
899 $header{classPublic}->add(<<END);
900 friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8: :Object> creationContext, v8::Isolate*);
901 friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Hand le<v8::Object> creationContext, v8::Isolate*);
902 friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Ha ndle<v8::Object> creationContext, v8::Isolate*);
903 END
904 } elsif ($interfaceName eq "HTMLUnknownElement") {
905 $header{classPublic}->add(<<END);
906 friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement *, v8::Handle<v8::Object> creationContext, v8::Isolate*);
907 END
908 } elsif ($interfaceName eq "Element") {
909 $header{classPublic}->add(<<END);
910 // This is a performance optimization hack. See V8Element::wrap.
911 friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationCon text, v8::Isolate*);
912 END
913 }
914 $header{classPublic}->add("\n"); # blank line to separate classPrivate
915
916 my $customToV8 = ExtendedAttributeContains($interface->extendedAttributes->{ "Custom"}, "ToV8");
917 my $passRefPtrType = GetPassRefPtrType($interface);
918 if (!$customToV8) {
919 $header{classPrivate}->add(<<END);
920 friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> cr eationContext, v8::Isolate*);
921 static v8::Handle<v8::Object> createWrapper(${passRefPtrType}, v8::Handle<v8 ::Object> creationContext, v8::Isolate*);
922 END
923 }
924
925 if ($customToV8) {
926 $header{nameSpaceWebCore}->add(<<END);
927
928 class ${nativeType};
929 v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContex t, v8::Isolate*);
930
931 template<class CallbackInfo>
932 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ${nativeType}* im pl)
933 {
934 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInf o.GetIsolate()));
935 }
936
937 template<class CallbackInfo>
938 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, ${nat iveType}* impl)
939 {
940 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackIn fo.GetIsolate()));
941 }
942
943 template<class CallbackInfo, class Wrappable>
944 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, ${nativeType} * impl, Wrappable*)
945 {
946 v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackIn fo.GetIsolate()));
947 }
948 END
949 } else {
950 if (NeedsSpecialWrap($interface)) {
951 $header{nameSpaceWebCore}->add(<<END);
952
953 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creation Context, v8::Isolate*);
954 END
955 } else {
956 $header{nameSpaceWebCore}->add(<<END);
957
958 inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> c reationContext, v8::Isolate* isolate)
959 {
960 ASSERT(impl);
961 ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl, isolate));
962 return ${v8ClassName}::createWrapper(impl, creationContext, isolate);
963 }
964 END
965 }
966
967 $header{nameSpaceWebCore}->add(<<END);
968
969 inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> cr eationContext, v8::Isolate* isolate)
970 {
971 if (UNLIKELY(!impl))
972 return v8::Null(isolate);
973 v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper<${v8ClassName}>(imp l, isolate);
974 if (!wrapper.IsEmpty())
975 return wrapper;
976 return wrap(impl, creationContext, isolate);
977 }
978
979 template<typename CallbackInfo>
980 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ${nativeType}* im pl)
981 {
982 if (UNLIKELY(!impl)) {
983 v8SetReturnValueNull(callbackInfo);
984 return;
985 }
986 if (DOMDataStore::setReturnValueFromWrapper<${v8ClassName}>(callbackInfo.Get ReturnValue(), impl))
987 return;
988 v8::Handle<v8::Object> wrapper = wrap(impl, callbackInfo.Holder(), callbackI nfo.GetIsolate());
989 v8SetReturnValue(callbackInfo, wrapper);
990 }
991
992 template<typename CallbackInfo>
993 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, ${nat iveType}* impl)
994 {
995 ASSERT(worldType(callbackInfo.GetIsolate()) == MainWorld);
996 if (UNLIKELY(!impl)) {
997 v8SetReturnValueNull(callbackInfo);
998 return;
999 }
1000 if (DOMDataStore::setReturnValueFromWrapperForMainWorld<${v8ClassName}>(call backInfo.GetReturnValue(), impl))
1001 return;
1002 v8::Handle<v8::Value> wrapper = wrap(impl, callbackInfo.Holder(), callbackIn fo.GetIsolate());
1003 v8SetReturnValue(callbackInfo, wrapper);
1004 }
1005
1006 template<class CallbackInfo, class Wrappable>
1007 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, ${nativeType} * impl, Wrappable* wrappable)
1008 {
1009 if (UNLIKELY(!impl)) {
1010 v8SetReturnValueNull(callbackInfo);
1011 return;
1012 }
1013 if (DOMDataStore::setReturnValueFromWrapperFast<${v8ClassName}>(callbackInfo .GetReturnValue(), impl, callbackInfo.Holder(), wrappable))
1014 return;
1015 v8::Handle<v8::Object> wrapper = wrap(impl, callbackInfo.Holder(), callbackI nfo.GetIsolate());
1016 v8SetReturnValue(callbackInfo, wrapper);
1017 }
1018 END
1019 }
1020
1021 $header{nameSpaceWebCore}->add(<<END);
1022
1023 inline v8::Handle<v8::Value> toV8($passRefPtrType impl, v8::Handle<v8::Object> c reationContext, v8::Isolate* isolate)
1024 {
1025 return toV8(impl.get(), creationContext, isolate);
1026 }
1027
1028 template<class CallbackInfo>
1029 inline void v8SetReturnValue(const CallbackInfo& callbackInfo, $passRefPtrType i mpl)
1030 {
1031 v8SetReturnValue(callbackInfo, impl.get());
1032 }
1033
1034 template<class CallbackInfo>
1035 inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, $pass RefPtrType impl)
1036 {
1037 v8SetReturnValueForMainWorld(callbackInfo, impl.get());
1038 }
1039
1040 template<class CallbackInfo, class Wrappable>
1041 inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, $passRefPtrTy pe impl, Wrappable* wrappable)
1042 {
1043 v8SetReturnValueFast(callbackInfo, impl.get(), wrappable);
1044 }
1045
1046 END
1047
1048 if ($interface->extendedAttributes->{"EventConstructor"}) {
1049 $header{nameSpaceWebCore}->add("bool initialize${implClassName}(${implCl assName}Init&, const Dictionary&, ExceptionState&, const v8::FunctionCallbackInf o<v8::Value>& info, const String& = \"\");\n\n");
1050 }
1051 }
1052
1053 sub GetInternalFields
1054 {
1055 my $interface = shift;
1056
1057 my @customInternalFields = ();
1058 # Event listeners on DOM nodes are explicitly supported in the GC controller .
1059 if (!InheritsInterface($interface, "Node") &&
1060 InheritsInterface($interface, "EventTarget")) {
1061 push(@customInternalFields, "eventListenerCacheIndex");
1062 }
1063 # Persistent handle is stored in the last internal field.
1064 # FIXME: Remove this internal field. Since we need either of a persistent ha ndle
1065 # (if the object is in oilpan) or a C++ pointer to the DOM object (if the ob ject is not in oilpan),
1066 # we can share the internal field between the two cases.
1067 if (IsWillBeGarbageCollectedType($interface->name)) {
1068 push(@customInternalFields, "persistentHandleIndex");
1069 }
1070 return @customInternalFields;
1071 }
1072
1073 sub GenerateHeaderCustomInternalFieldIndices
1074 {
1075 my $interface = shift;
1076 my @customInternalFields = GetInternalFields($interface);
1077 my $customFieldCounter = 0;
1078 foreach my $customInternalField (@customInternalFields) {
1079 $header{classPublic}->add(<<END);
1080 static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter};
1081 END
1082 $customFieldCounter++;
1083 }
1084 $header{classPublic}->add(<<END);
1085 static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + $ {customFieldCounter};
1086 END
1087 }
1088
1089 sub GenerateHeaderNamedAndIndexedPropertyAccessors
1090 {
1091 my $interface = shift;
1092
1093 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
1094 my $hasCustomIndexedGetter = $indexedGetterFunction && $indexedGetterFunctio n->extendedAttributes->{"Custom"};
1095
1096 my $indexedSetterFunction = GetIndexedSetterFunction($interface);
1097 my $hasCustomIndexedSetter = $indexedSetterFunction && $indexedSetterFunctio n->extendedAttributes->{"Custom"};
1098
1099 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface);
1100 my $hasCustomIndexedDeleters = $indexedDeleterFunction && $indexedDeleterFun ction->extendedAttributes->{"Custom"};
1101
1102 my $namedGetterFunction = GetNamedGetterFunction($interface);
1103 my $hasCustomNamedGetter = $namedGetterFunction && HasCustomPropertyGetter($ namedGetterFunction->extendedAttributes);
1104
1105 my $namedSetterFunction = GetNamedSetterFunction($interface);
1106 my $hasCustomNamedSetter = $namedSetterFunction && $namedSetterFunction->ext endedAttributes->{"Custom"};
1107
1108 my $namedDeleterFunction = GetNamedDeleterFunction($interface);
1109 my $hasCustomNamedDeleter = $namedDeleterFunction && $namedDeleterFunction-> extendedAttributes->{"Custom"};
1110
1111 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction- >extendedAttributes->{"NotEnumerable"};
1112 my $hasCustomNamedEnumerator = $namedEnumeratorFunction && ExtendedAttribute Contains($namedGetterFunction->extendedAttributes->{"Custom"}, "PropertyEnumerat or");
1113 my $hasCustomNamedQuery = $namedEnumeratorFunction && ExtendedAttributeConta ins($namedGetterFunction->extendedAttributes->{"Custom"}, "PropertyQuery");
1114
1115 if ($hasCustomIndexedGetter) {
1116 $header{classPublic}->add(" static void indexedPropertyGetterCustom(u int32_t, const v8::PropertyCallbackInfo<v8::Value>&);\n");
1117 }
1118
1119 if ($hasCustomIndexedSetter) {
1120 $header{classPublic}->add(" static void indexedPropertySetterCustom(u int32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n");
1121 }
1122
1123 if ($hasCustomIndexedDeleters) {
1124 $header{classPublic}->add(" static void indexedPropertyDeleterCustom( uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);\n");
1125 }
1126
1127 if ($hasCustomNamedGetter) {
1128 $header{classPublic}->add(" static void namedPropertyGetterCustom(v8: :Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&);\n");
1129 }
1130
1131 if ($hasCustomNamedSetter) {
1132 $header{classPublic}->add(" static void namedPropertySetterCustom(v8: :Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Val ue>&);\n");
1133 }
1134
1135 if ($hasCustomNamedQuery) {
1136 $header{classPublic}->add(" static void namedPropertyQueryCustom(v8:: Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer>&);\n");
1137 }
1138
1139 if ($hasCustomNamedDeleter) {
1140 $header{classPublic}->add(" static void namedPropertyDeleterCustom(v8 ::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean>&);\n");
1141 }
1142
1143 if ($hasCustomNamedEnumerator) {
1144 $header{classPublic}->add(" static void namedPropertyEnumeratorCustom (const v8::PropertyCallbackInfo<v8::Array>&);\n");
1145 }
1146 }
1147
1148 sub GenerateHeaderLegacyCallAsFunction
1149 {
1150 my $interface = shift;
1151
1152 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "L egacyCallAsFunction")) {
1153 $header{classPublic}->add(" static void legacyCallCustom(const v8::Fu nctionCallbackInfo<v8::Value>&);\n");
1154 }
1155 }
1156
1157 sub HasActivityLogging
1158 {
1159 my $forMainWorldSuffix = shift;
1160 my $attrExt = shift;
1161 my $access = shift;
1162
1163 if (!$attrExt->{"ActivityLogging"}) {
1164 return 0;
1165 }
1166 my $logAllAccess = ($attrExt->{"ActivityLogging"} =~ /^For/); # No prefix, starts with For*Worlds suffix
1167 my $logGetter = ($attrExt->{"ActivityLogging"} =~ /^Getter/);
1168 my $logSetter = ($attrExt->{"ActivityLogging"} =~ /^Setter/);
1169 my $logOnlyIsolatedWorlds = ($attrExt->{"ActivityLogging"} =~ /ForIsolatedWo rlds$/);
1170
1171 if ($logOnlyIsolatedWorlds && $forMainWorldSuffix eq "ForMainWorld") {
1172 return 0;
1173 }
1174 return $logAllAccess || ($logGetter && $access eq "Getter") || ($logSetter & & $access eq "Setter");
1175 }
1176
1177 sub IsConstructable
1178 {
1179 my $interface = shift;
1180
1181 return $interface->extendedAttributes->{"CustomConstructor"} || $interface-> extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"EventCo nstructor"};
1182 }
1183
1184 sub HasCustomConstructor
1185 {
1186 my $interface = shift;
1187
1188 return $interface->extendedAttributes->{"CustomConstructor"};
1189 }
1190
1191 sub HasCustomGetter
1192 {
1193 my $attrExt = shift;
1194 my $custom = $attrExt->{"Custom"};
1195 return $custom && ($custom eq "VALUE_IS_MISSING" || $custom eq "Getter");
1196 }
1197
1198 sub HasCustomSetter
1199 {
1200 my $attribute = shift;
1201 my $custom = $attribute->extendedAttributes->{"Custom"};
1202 return $custom && ($custom eq "VALUE_IS_MISSING" || $custom eq "Setter") && !IsReadonly($attribute);
1203 }
1204
1205 sub HasCustomMethod
1206 {
1207 my $attrExt = shift;
1208 return $attrExt->{"Custom"};
1209 }
1210
1211 sub HasCustomPropertyGetter
1212 {
1213 my $attrExt = shift;
1214 my $custom = $attrExt->{"Custom"};
1215 return $custom && ($custom eq "VALUE_IS_MISSING" || ExtendedAttributeContain s($custom, "PropertyGetter"));
1216 }
1217
1218 sub IsReadonly
1219 {
1220 my $attribute = shift;
1221 my $attrExt = $attribute->extendedAttributes;
1222 return $attribute->isReadOnly && !$attrExt->{"Replaceable"} && !$attrExt->{" PutForwards"};
1223 }
1224
1225 sub GetV8ClassName
1226 {
1227 my $interface = shift;
1228 return "V8" . $interface->name;
1229 }
1230
1231 sub GetImplName
1232 {
1233 my $interfaceOrAttributeOrFunction = shift;
1234 return $interfaceOrAttributeOrFunction->extendedAttributes->{"ImplementedAs" } || $interfaceOrAttributeOrFunction->name;
1235 }
1236
1237 sub GetImplNameFromImplementedBy
1238 {
1239 my $implementedBy = shift;
1240
1241 my $interface = ParseInterface($implementedBy);
1242
1243 return $interface->extendedAttributes->{"ImplementedAs"} || $implementedBy;
1244 }
1245
1246 sub GenerateDomainSafeFunctionGetter
1247 {
1248 my $function = shift;
1249 my $interface = shift;
1250 my $forMainWorldSuffix = shift;
1251
1252 my $implClassName = GetImplName($interface);
1253 my $v8ClassName = GetV8ClassName($interface);
1254 my $funcName = $function->name;
1255
1256 my $functionLength = GetFunctionLength($function);
1257 my $signature = "v8::Signature::New(info.GetIsolate(), ${v8ClassName}::domTe mplate(info.GetIsolate(), currentWorldType))";
1258 if ($function->extendedAttributes->{"DoNotCheckSignature"}) {
1259 $signature = "v8::Local<v8::Signature>()";
1260 }
1261
1262 my $newTemplateParams = "${implClassName}V8Internal::${funcName}MethodCallba ck${forMainWorldSuffix}, v8Undefined(), $signature";
1263
1264 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1265 $implementation{nameSpaceInternal}->add(<<END);
1266 static void ${funcName}OriginSafeMethodGetter${forMainWorldSuffix}(const v8::Pro pertyCallbackInfo<v8::Value>& info)
1267 {
1268 static int domTemplateKey; // This address is used for a key to look up the dom template.
1269 WrapperWorldType currentWorldType = worldType(info.GetIsolate());
1270 V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate());
1271 v8::Handle<v8::FunctionTemplate> privateTemplate = data->domTemplate(current WorldType, &domTemplateKey, $newTemplateParams, $functionLength);
1272
1273 v8::Handle<v8::Object> holder = ${v8ClassName}::findInstanceInPrototypeChain (info.This(), info.GetIsolate());
1274 if (holder.IsEmpty()) {
1275 // This is only reachable via |object.__proto__.func|, in which case it
1276 // has already passed the same origin security check
1277 v8SetReturnValue(info, privateTemplate->GetFunction());
1278 return;
1279 }
1280 ${implClassName}* imp = ${v8ClassName}::toNative(holder);
1281 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame (), DoNotReportSecurityError)) {
1282 static int sharedTemplateKey; // This address is used for a key to look up the dom template.
1283 v8::Handle<v8::FunctionTemplate> sharedTemplate = data->domTemplate(curr entWorldType, &sharedTemplateKey, $newTemplateParams, $functionLength);
1284 v8SetReturnValue(info, sharedTemplate->GetFunction());
1285 return;
1286 }
1287
1288 v8::Local<v8::Value> hiddenValue = getHiddenValue(info.GetIsolate(), info.Th is(), "${funcName}");
1289 if (!hiddenValue.IsEmpty()) {
1290 v8SetReturnValue(info, hiddenValue);
1291 return;
1292 }
1293
1294 v8SetReturnValue(info, privateTemplate->GetFunction());
1295 }
1296
1297 END
1298 $implementation{nameSpaceInternal}->add(<<END);
1299 static void ${funcName}OriginSafeMethodGetterCallback${forMainWorldSuffix}(v8::L ocal<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)
1300 {
1301 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
1302 ${implClassName}V8Internal::${funcName}OriginSafeMethodGetter${forMainWorldS uffix}(info);
1303 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
1304 }
1305
1306 END
1307 }
1308
1309 sub GenerateDomainSafeFunctionSetter
1310 {
1311 my $interface = shift;
1312
1313 my $interfaceName = $interface->name();
1314 my $implClassName = GetImplName($interface);
1315 my $v8ClassName = GetV8ClassName($interface);
1316
1317 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1318 $implementation{nameSpaceInternal}->add(<<END);
1319 static void ${implClassName}OriginSafeMethodSetter(v8::Local<v8::String> name, v 8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)
1320 {
1321 v8::Handle<v8::Object> holder = ${v8ClassName}::findInstanceInPrototypeChain (info.This(), info.GetIsolate());
1322 if (holder.IsEmpty())
1323 return;
1324 ${implClassName}* imp = ${v8ClassName}::toNative(holder);
1325 v8::String::Utf8Value attributeName(name);
1326 ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "${interfaceName}", info.Holder(), info.GetIsolate());
1327 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame (), exceptionState)) {
1328 exceptionState.throwIfNeeded();
1329 return;
1330 }
1331
1332 setHiddenValue(info.GetIsolate(), info.This(), name, jsValue);
1333 }
1334
1335 static void ${implClassName}OriginSafeMethodSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)
1336 {
1337 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter");
1338 ${implClassName}V8Internal::${implClassName}OriginSafeMethodSetter(name, jsV alue, info);
1339 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
1340 }
1341
1342 END
1343 }
1344
1345 sub GenerateConstructorGetter
1346 {
1347 my $interface = shift;
1348 my $implClassName = GetImplName($interface);
1349
1350 $implementation{nameSpaceInternal}->add(<<END);
1351 static void ${implClassName}ConstructorGetter(v8::Local<v8::String>, const v8::P ropertyCallbackInfo<v8::Value>& info)
1352 {
1353 v8::Handle<v8::Value> data = info.Data();
1354 ASSERT(data->IsExternal());
1355 V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->Cre ationContext());
1356 if (!perContextData)
1357 return;
1358 v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::u nwrap(data)));
1359 }
1360
1361 END
1362 }
1363
1364 sub GenerateFeatureObservation
1365 {
1366 my $measureAs = shift;
1367
1368 if ($measureAs) {
1369 AddToImplIncludes("core/frame/UseCounter.h");
1370 return " UseCounter::count(callingExecutionContext(info.GetIsolate()) , UseCounter::${measureAs});\n";
1371 }
1372
1373 return "";
1374 }
1375
1376 sub GenerateDeprecationNotification
1377 {
1378 my $deprecateAs = shift;
1379 if ($deprecateAs) {
1380 AddToImplIncludes("core/frame/UseCounter.h");
1381 return " UseCounter::countDeprecation(callingExecutionContext(info.Ge tIsolate()), UseCounter::${deprecateAs});\n";
1382 }
1383 return "";
1384 }
1385
1386 sub GenerateActivityLogging
1387 {
1388 my $accessType = shift;
1389 my $interface = shift;
1390 my $propertyName = shift;
1391
1392 my $interfaceName = $interface->name;
1393
1394 AddToImplIncludes("bindings/v8/V8DOMActivityLogger.h");
1395
1396 my $code = "";
1397 if ($accessType eq "Method") {
1398 $code .= <<END;
1399 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->Ge tCurrentContext());
1400 if (contextData && contextData->activityLogger()) {
1401 Vector<v8::Handle<v8::Value> > loggerArgs = toNativeArguments<v8::Handle <v8::Value> >(info, 0);
1402 contextData->activityLogger()->log("${interfaceName}.${propertyName}", i nfo.Length(), loggerArgs.data(), "${accessType}");
1403 }
1404 END
1405 } elsif ($accessType eq "Setter") {
1406 $code .= <<END;
1407 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->Ge tCurrentContext());
1408 if (contextData && contextData->activityLogger()) {
1409 v8::Handle<v8::Value> loggerArg[] = { jsValue };
1410 contextData->activityLogger()->log("${interfaceName}.${propertyName}", 1 , &loggerArg[0], "${accessType}");
1411 }
1412 END
1413 } elsif ($accessType eq "Getter") {
1414 $code .= <<END;
1415 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->Ge tCurrentContext());
1416 if (contextData && contextData->activityLogger())
1417 contextData->activityLogger()->log("${interfaceName}.${propertyName}", 0 , 0, "${accessType}");
1418 END
1419 } else {
1420 die "Unrecognized activity logging access type";
1421 }
1422
1423 return $code;
1424 }
1425
1426 sub GenerateNormalAttributeGetterCallback
1427 {
1428 my $attribute = shift;
1429 my $interface = shift;
1430 my $forMainWorldSuffix = shift;
1431 my $exposeJSAccessors = shift;
1432
1433 my $implClassName = GetImplName($interface);
1434 my $v8ClassName = GetV8ClassName($interface);
1435 my $attrExt = $attribute->extendedAttributes;
1436 my $attrName = $attribute->name;
1437
1438 my $conditionalString = GenerateConditionalString($attribute);
1439 my $code = "";
1440 $code .= "#if ${conditionalString}\n" if $conditionalString;
1441
1442 if ($exposeJSAccessors) {
1443 $code .= "static void ${attrName}AttributeGetterCallback${forMainWorldSu ffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n";
1444 } else {
1445 $code .= "static void ${attrName}AttributeGetterCallback${forMainWorldSu ffix}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)\n" ;
1446 }
1447 $code .= "{\n";
1448 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMGetter\");\n";
1449 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"});
1450 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"});
1451 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Getter")) {
1452 $code .= GenerateActivityLogging("Getter", $interface, "${attrName}");
1453 }
1454 if (HasCustomGetter($attrExt)) {
1455 $code .= " ${v8ClassName}::${attrName}AttributeGetterCustom(info);\n" ;
1456 } else {
1457 $code .= " ${implClassName}V8Internal::${attrName}AttributeGetter${fo rMainWorldSuffix}(info);\n";
1458 }
1459 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
1460 $code .= "}\n";
1461 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1462 $code .= "\n";
1463
1464 $implementation{nameSpaceInternal}->add($code);
1465 }
1466
1467 sub GetCachedAttribute
1468 {
1469 my $attribute = shift;
1470 my $attrExt = $attribute->extendedAttributes;
1471 if (($attribute->type eq "any" || $attribute->type eq "SerializedScriptValue ") && $attrExt->{"CachedAttribute"}) {
1472 return $attrExt->{"CachedAttribute"};
1473 }
1474 return "";
1475 }
1476
1477 sub GenerateNormalAttributeGetter
1478 {
1479 my $attribute = shift;
1480 my $interface = shift;
1481 my $forMainWorldSuffix = shift;
1482 my $exposeJSAccessors = shift;
1483
1484 my $interfaceName = $interface->name;
1485 my $implClassName = GetImplName($interface);
1486 my $v8ClassName = GetV8ClassName($interface);
1487 my $attrExt = $attribute->extendedAttributes;
1488 my $attrName = $attribute->name;
1489 my $attrType = $attribute->type;
1490 my $attrCached = GetCachedAttribute($attribute);
1491
1492 if (HasCustomGetter($attrExt)) {
1493 return;
1494 }
1495
1496 AssertNotSequenceType($attrType);
1497 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttribu tes, "");
1498 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName);
1499
1500 my $conditionalString = GenerateConditionalString($attribute);
1501 my $code = "";
1502 $code .= "#if ${conditionalString}\n" if $conditionalString;
1503 if ($exposeJSAccessors) {
1504 $code .= "static void ${attrName}AttributeGetter${forMainWorldSuffix}(co nst v8::FunctionCallbackInfo<v8::Value>& info)\n";
1505 } else {
1506 $code .= "static void ${attrName}AttributeGetter${forMainWorldSuffix}(co nst v8::PropertyCallbackInfo<v8::Value>& info)\n";
1507 }
1508 $code .= "{\n";
1509 if ($svgNativeType) {
1510 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceNam e);
1511 if ($svgWrappedNativeType =~ /List/) {
1512 $code .= <<END;
1513 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder());
1514 END
1515 } else {
1516 $code .= <<END;
1517 $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder());
1518 $svgWrappedNativeType& impInstance = wrapper->propertyReference();
1519 $svgWrappedNativeType* imp = &impInstance;
1520 END
1521 }
1522 } elsif ($attrExt->{"OnPrototype"} || $attrExt->{"Unforgeable"}) {
1523 if ($interfaceName eq "Window") {
1524 $code .= <<END;
1525 v8::Handle<v8::Object> holder = info.Holder();
1526 END
1527 } else {
1528 # perform lookup first
1529 $code .= <<END;
1530 v8::Handle<v8::Object> holder = ${v8ClassName}::findInstanceInPrototypeChain (info.This(), info.GetIsolate());
1531 if (holder.IsEmpty())
1532 return;
1533 END
1534 }
1535 $code .= <<END;
1536 ${implClassName}* imp = ${v8ClassName}::toNative(holder);
1537 END
1538 } else {
1539 my $reflect = $attribute->extendedAttributes->{"Reflect"};
1540 my $url = $attribute->extendedAttributes->{"URL"};
1541 if ($reflect && !$url && InheritsInterface($interface, "Node") && $attrT ype eq "DOMString") {
1542 # Generate super-compact call for regular attribute getter:
1543 my ($functionName, @arguments) = GetterExpression($interfaceName, $a ttribute);
1544 my $getterExpression = "imp->${functionName}(" . join(", ", @argumen ts) . ")";
1545 $code .= " Element* imp = V8Element::toNative(info.Holder());\n";
1546 if ($attribute->extendedAttributes->{"ReflectOnly"}) {
1547 $code .= " String resultValue = ${getterExpression};\n";
1548 $code .= GenerateReflectOnlyCheck($attribute->extendedAttributes , " ");
1549 $getterExpression = "resultValue";
1550 }
1551 $code .= " v8SetReturnValueString(info, ${getterExpression}, info .GetIsolate());\n";
1552 $code .= "}\n";
1553 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1554 $code .= "\n";
1555 $implementation{nameSpaceInternal}->add($code);
1556 return;
1557 # Skip the rest of the function!
1558 }
1559 my $imp = 0;
1560 if ($attrCached) {
1561 $imp = 1;
1562 $code .= <<END;
1563 v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "${a ttrName}");
1564 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1565 if (!imp->$attrCached()) {
1566 v8::Handle<v8::Value> jsValue = getHiddenValue(info.GetIsolate(), info.H older(), propertyName);
1567 if (!jsValue.IsEmpty()) {
1568 v8SetReturnValue(info, jsValue);
1569 return;
1570 }
1571 }
1572 END
1573 }
1574 if (!$attribute->isStatic && !$imp) {
1575 $code .= <<END;
1576 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1577 END
1578 }
1579 }
1580
1581 my $raisesException = $attribute->extendedAttributes->{"RaisesException"};
1582 my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_ MISSING" or $raisesException eq "Getter");
1583 if ($useExceptions || $attribute->extendedAttributes->{"CheckSecurity"}) {
1584 $code .= " ExceptionState exceptionState(ExceptionState::GetterContex t, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
1585 }
1586
1587 # Generate security checks if necessary
1588 if ($attribute->extendedAttributes->{"CheckSecurity"}) {
1589 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1590 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsol ate(), imp->" . GetImplName($attribute) . "(), exceptionState)) {\n";
1591 $code .= " v8SetReturnValueNull(info);\n";
1592 $code .= " exceptionState.throwIfNeeded();\n";
1593 $code .= " return;\n";
1594 $code .= " }\n";
1595 }
1596
1597 my $isNullable = $attribute->isNullable;
1598 if ($isNullable) {
1599 $code .= " bool isNull = false;\n";
1600 }
1601
1602 my $getterString;
1603 my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute );
1604 push(@arguments, "isNull") if $isNullable;
1605 push(@arguments, "exceptionState") if $useExceptions;
1606 if ($attribute->extendedAttributes->{"ImplementedBy"}) {
1607 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
1608 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy) ;
1609 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedBy ImplName));
1610 if (!$attribute->isStatic) {
1611 $code .= " ASSERT(imp);\n";
1612 unshift(@arguments, "*imp");
1613 }
1614 $functionName = "${implementedByImplName}::${functionName}";
1615 } elsif ($attribute->isStatic) {
1616 $functionName = "${implClassName}::${functionName}";
1617 } else {
1618 $functionName = "imp->${functionName}";
1619 }
1620 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"Cal lWith"}, " ", 0);
1621 $code .= $subCode;
1622 unshift(@arguments, @$arg);
1623 $getterString = "${functionName}(" . join(", ", @arguments) . ")";
1624
1625 my $expression;
1626 if ($attribute->type eq "EventHandler" && $interface->name eq "Window") {
1627 $code .= " if (!imp->document())\n";
1628 $code .= " return;\n";
1629 }
1630
1631 if ($useExceptions || $isNullable) {
1632 if ($nativeType =~ /^V8StringResource/) {
1633 $code .= " " . ConvertToV8StringResource($attribute, $nativeType, "cppValue", $getterString) . ";\n";
1634 } else {
1635 $code .= " $nativeType jsValue = $getterString;\n";
1636 $getterString = "jsValue";
1637 }
1638
1639 if ($isNullable) {
1640 $code .= " if (isNull) {\n";
1641 $code .= " v8SetReturnValueNull(info);\n";
1642 $code .= " return;\n";
1643 $code .= " }\n";
1644 }
1645
1646 if ($useExceptions) {
1647 if ($useExceptions) {
1648 $code .= " if (UNLIKELY(exceptionState.throwIfNeeded()))\n";
1649 $code .= " return;\n";
1650 }
1651
1652 if (ExtendedAttributeContains($attribute->extendedAttributes->{"Call With"}, "ScriptState")) {
1653 $code .= " if (state.hadException()) {\n";
1654 $code .= " throwError(state.exception(), info.GetIsolate( ));\n";
1655 $code .= " return;\n";
1656 $code .= " }\n";
1657 }
1658 }
1659
1660 $expression = "jsValue";
1661 $expression .= ".release()" if (IsRefPtrType($attrType));
1662 } else {
1663 # Can inline the function call into the return statement to avoid overhe ad of using a Ref<> temporary
1664 $expression = $getterString;
1665 }
1666
1667 if (ShouldKeepAttributeAlive($interface, $attribute, $attrType)) {
1668 my $arrayType = GetArrayType($attrType);
1669 if ($arrayType) {
1670 $code .= " v8SetReturnValue(info, v8Array(${getterString}, info.G etIsolate()));\n";
1671 $code .= "}\n\n";
1672 $implementation{nameSpaceInternal}->add($code);
1673 return;
1674 }
1675
1676 # Check for a wrapper in the wrapper cache. If there is one, we know tha t a hidden reference has already
1677 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
1678 my $nativeReturnType = GetNativeType($attrType);
1679 my $v8ReturnType = "V8" . $attrType;
1680 $code .= " $nativeReturnType result = ${getterString};\n";
1681 if ($forMainWorldSuffix) {
1682 $code .= " if (result && DOMDataStore::setReturnValueFromWrapper$ {forMainWorldSuffix}<${v8ReturnType}>(info.GetReturnValue(), result.get()))\n";
1683 } else {
1684 $code .= " if (result && DOMDataStore::setReturnValueFromWrapper< ${v8ReturnType}>(info.GetReturnValue(), result.get()))\n";
1685 }
1686 $code .= " return;\n";
1687 $code .= " v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Ho lder(), info.GetIsolate());\n";
1688 $code .= " if (!wrapper.IsEmpty()) {\n";
1689 $code .= " setHiddenValue(info.GetIsolate(), info.Holder(), \"${a ttrName}\", wrapper);\n";
1690 $code .= " v8SetReturnValue(info, wrapper);\n";
1691 $code .= " }\n";
1692 $code .= "}\n";
1693 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1694 $code .= "\n";
1695 $implementation{nameSpaceInternal}->add($code);
1696 return;
1697 }
1698
1699 if ((IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") a nd IsSVGTypeNeedingTearOff($attrType)) {
1700 AddToImplIncludes("V8$attrType.h");
1701 my $svgNativeType = GetSVGTypeNeedingTearOff($attrType);
1702 # Convert from abstract SVGProperty to real type, so the right toJS() me thod can be invoked.
1703 if ($forMainWorldSuffix eq "ForMainWorld") {
1704 $code .= " v8SetReturnValueForMainWorld(info, static_cast<$svgNat iveType*>($expression));\n";
1705 } else {
1706 $code .= " v8SetReturnValueFast(info, static_cast<$svgNativeType* >($expression), imp);\n";
1707 }
1708 } elsif (IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$ /) {
1709 AddToImplIncludes("V8$attrType.h");
1710 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h");
1711 my $tearOffType = GetSVGTypeNeedingTearOff($attrType);
1712 my $wrappedValue;
1713 if ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
1714 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expres sion))";
1715 } else {
1716 $wrappedValue = "WTF::getPtr(${tearOffType}::create($expression) )";
1717 }
1718 if ($forMainWorldSuffix eq "ForMainWorld") {
1719 $code .= " v8SetReturnValueForMainWorld(info, $wrappedValue);\n";
1720 } else {
1721 $code .= " v8SetReturnValueFast(info, $wrappedValue, imp);\n";
1722 }
1723 } elsif ($attrCached) {
1724 if ($attribute->type eq "SerializedScriptValue") {
1725 $code .= <<END;
1726 RefPtr<SerializedScriptValue> serialized = $getterString;
1727 ScriptValue jsValue = serialized ? serialized->deserialize() : v8::Handle<v8 ::Value>(v8::Null(info.GetIsolate()));
1728 setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, jsValue);
1729 v8SetReturnValue(info, jsValue);
1730 END
1731 } else {
1732 if (!$useExceptions && !$isNullable) {
1733 $code .= <<END;
1734 ScriptValue jsValue = $getterString;
1735 END
1736 }
1737 $code .= <<END;
1738 setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, jsValue.v8Val ue());
1739 v8SetReturnValue(info, jsValue.v8Value());
1740 END
1741 }
1742 } elsif ($attribute->type eq "EventHandler") {
1743 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h");
1744 # FIXME: Pass the main world ID for main-world-only getters.
1745 my ($functionName, @arguments) = GetterExpression($interfaceName, $attri bute);
1746 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
1747 if ($implementedBy) {
1748 my $implementedByImplName = GetImplNameFromImplementedBy($implemente dBy);
1749 $functionName = "${implementedByImplName}::${functionName}";
1750 $code .= " ASSERT(imp);\n";
1751 push(@arguments, "*imp");
1752 } else {
1753 $functionName = "imp->${functionName}";
1754 }
1755 $code .= " EventListener* jsValue = ${functionName}(" . join(", ", @a rguments) . ");\n";
1756 $code .= " v8SetReturnValue(info, jsValue ? v8::Handle<v8::Value>(V8A bstractEventListener::cast(jsValue)->getListenerObject(imp->executionContext())) : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())));\n";
1757 } else {
1758 my $nativeValue = NativeToJSValue($attribute->type, $attribute->extended Attributes, $expression, " ", "", "info.GetIsolate()", "info", "imp", $forMai nWorldSuffix, "return");
1759 $code .= "${nativeValue}\n";
1760 }
1761
1762 $code .= "}\n"; # end of getter
1763 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1764 $code .= "\n";
1765 $implementation{nameSpaceInternal}->add($code);
1766 }
1767
1768 sub ShouldKeepAttributeAlive
1769 {
1770 my ($interface, $attribute, $returnType) = @_;
1771 my $attrName = $attribute->name;
1772
1773 # For readonly attributes (including Replaceable), as a general rule, for
1774 # performance reasons we keep the attribute wrapper alive while the owner
1775 # wrapper is alive, because the attribute never changes.
1776 return 0 if !IsWrapperType($returnType);
1777 return 0 if !IsReadonly($attribute) && !$attribute->extendedAttributes->{"Re placeable"};
1778
1779 # However, there are a couple of exceptions.
1780
1781 # Node lifetime is managed by object grouping.
1782 return 0 if InheritsInterface($interface, "Node");
1783 return 0 if IsDOMNodeType($returnType);
1784
1785 # To avoid adding a reference to itself.
1786 # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove this hack
1787 # depending on the attribute name.
1788 return 0 if $attrName eq "self";
1789
1790 # FIXME: Remove these hard-coded hacks.
1791 return 0 if $returnType eq "EventTarget";
1792 return 0 if $returnType eq "Window";
1793 return 0 if $returnType =~ /SVG/;
1794 return 0 if $returnType =~ /HTML/;
1795
1796 return 1;
1797 }
1798
1799 sub GenerateReplaceableAttributeSetterCallback
1800 {
1801 my $interface = shift;
1802 my $implClassName = GetImplName($interface);
1803
1804 my $code = "";
1805 $code .= "static void ${implClassName}ReplaceableAttributeSetterCallback(v8: :Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbac kInfo<void>& info)\n";
1806 $code .= "{\n";
1807 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"Measur eAs"});
1808 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"D eprecateAs"});
1809 $code .= GenerateCustomElementInvocationScopeIfNeeded($interface->extendedAt tributes);
1810 if (HasActivityLogging("", $interface->extendedAttributes, "Setter")) {
1811 die "IDL error: ActivityLog attribute cannot exist on a ReplacableAttri buteSetterCallback";
1812 }
1813 $code .= " ${implClassName}V8Internal::${implClassName}ReplaceableAttribu teSetter(name, jsValue, info);\n";
1814 $code .= "}\n\n";
1815 $implementation{nameSpaceInternal}->add($code);
1816 }
1817
1818 sub GenerateReplaceableAttributeSetter
1819 {
1820 my $interface = shift;
1821
1822 my $interfaceName = $interface->name();
1823 my $implClassName = GetImplName($interface);
1824 my $v8ClassName = GetV8ClassName($interface);
1825
1826 my $code = "";
1827 $code .= <<END;
1828 static void ${implClassName}ReplaceableAttributeSetter(v8::Local<v8::String> nam e, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)
1829 {
1830 END
1831 if ($interface->extendedAttributes->{"CheckSecurity"}) {
1832 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1833 $code .= <<END;
1834 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1835 v8::String::Utf8Value attributeName(name);
1836 ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "${interfaceName}", info.Holder(), info.GetIsolate());
1837 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame (), exceptionState)) {
1838 exceptionState.throwIfNeeded();
1839 return;
1840 }
1841 END
1842 }
1843
1844 $code .= <<END;
1845 info.This()->ForceSet(name, jsValue);
1846 }
1847
1848 END
1849 $implementation{nameSpaceInternal}->add($code);
1850 }
1851
1852 sub GenerateCustomElementInvocationScopeIfNeeded
1853 {
1854 my $code = "";
1855 my $ext = shift;
1856
1857 if ($ext->{"CustomElementCallbacks"} or $ext->{"Reflect"}) {
1858 AddToImplIncludes("core/dom/custom/CustomElementCallbackDispatcher.h");
1859 $code .= <<END;
1860 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
1861 END
1862 }
1863 return $code;
1864 }
1865
1866 sub GenerateNormalAttributeSetterCallback
1867 {
1868 my $attribute = shift;
1869 my $interface = shift;
1870 my $forMainWorldSuffix = shift;
1871 my $exposeJSAccessors = shift;
1872
1873 my $implClassName = GetImplName($interface);
1874 my $v8ClassName = GetV8ClassName($interface);
1875 my $attrExt = $attribute->extendedAttributes;
1876 my $attrName = $attribute->name;
1877
1878 my $conditionalString = GenerateConditionalString($attribute);
1879 my $code = "";
1880 $code .= "#if ${conditionalString}\n" if $conditionalString;
1881
1882 if ($exposeJSAccessors) {
1883 $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSu ffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n";
1884 $code .= "{\n";
1885 $code .= " v8::Local<v8::Value> jsValue = info[0];\n";
1886 } else {
1887 $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSu ffix}(v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCal lbackInfo<void>& info)\n";
1888 $code .= "{\n";
1889 }
1890 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMSetter\");\n";
1891 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"});
1892 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"});
1893 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Setter")) {
1894 $code .= GenerateActivityLogging("Setter", $interface, "${attrName}");
1895 }
1896 $code .= GenerateCustomElementInvocationScopeIfNeeded($attrExt);
1897 if (HasCustomSetter($attribute)) {
1898 $code .= " ${v8ClassName}::${attrName}AttributeSetterCustom(jsValue, info);\n";
1899 } else {
1900 $code .= " ${implClassName}V8Internal::${attrName}AttributeSetter${fo rMainWorldSuffix}(jsValue, info);\n";
1901 }
1902 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
1903 $code .= "}\n";
1904 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
1905 $code .= "\n";
1906 $implementation{nameSpaceInternal}->add($code);
1907 }
1908
1909 sub FindAttributeWithName
1910 {
1911 my $interface = shift;
1912 my $attrName = shift;
1913
1914 foreach my $attribute (@{$interface->attributes}) {
1915 if ($attribute->name eq $attrName) {
1916 return $attribute;
1917 }
1918 }
1919 }
1920
1921 sub GenerateNormalAttributeSetter
1922 {
1923 my $attribute = shift;
1924 my $interface = shift;
1925 my $forMainWorldSuffix = shift;
1926 my $exposeJSAccessors = shift;
1927
1928 my $interfaceName = $interface->name;
1929 my $implClassName = GetImplName($interface);
1930 my $v8ClassName = GetV8ClassName($interface);
1931 my $attrName = $attribute->name;
1932 my $attrExt = $attribute->extendedAttributes;
1933 my $attrType = $attribute->type;
1934 my $attrCached = GetCachedAttribute($attribute);
1935
1936 if (HasCustomSetter($attribute)) {
1937 return;
1938 }
1939
1940 my $conditionalString = GenerateConditionalString($attribute);
1941 my $code = "";
1942 $code .= "#if ${conditionalString}\n" if $conditionalString;
1943 if ($exposeJSAccessors) {
1944 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8 ::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info)\n";
1945 } else {
1946 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8 ::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n";
1947 }
1948 $code .= "{\n";
1949
1950 my $raisesException = $attribute->extendedAttributes->{"RaisesException"};
1951 my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_ MISSING" or $raisesException eq "Setter");
1952 my $hasStrictTypeChecking = 1 if ($interface->extendedAttributes->{"StrictTy peChecking"} || $attribute->extendedAttributes->{"StrictTypeChecking"}) && IsWra pperType($attrType); # Currently only actually check interface types
1953
1954 # Can throw exceptions from accessors or during type conversion.
1955 my $isIntegerType = IsIntegerType($attribute->type);
1956
1957 # We throw exceptions using 'ExceptionState' if the attribute explicitly
1958 # claims that exceptions may be raised, or if a strict type check might
1959 # fail, or if we're dealing with SVG, which does strange things with
1960 # tearoffs and read-only wrappers.
1961 if ($useExceptions or $hasStrictTypeChecking or GetSVGTypeNeedingTearOff($in terfaceName) or GetSVGTypeNeedingTearOff($attrType) or $isIntegerType) {
1962 $code .= " ExceptionState exceptionState(ExceptionState::SetterContex t, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
1963 }
1964
1965 # If the "StrictTypeChecking" extended attribute is present, and the
1966 # attribute's type is an interface type, then if the incoming value does not
1967 # implement that interface, a TypeError is thrown rather than silently
1968 # passing NULL to the C++ code.
1969 # Per the Web IDL and ECMAScript specifications, incoming values can always
1970 # be converted to both strings and numbers, so do not throw TypeError if the
1971 # attribute is of these types.
1972 if ($hasStrictTypeChecking) {
1973 $code .= " if (!isUndefinedOrNull(jsValue) && !V8${attrType}::hasInst ance(jsValue, info.GetIsolate())) {\n";
1974 $code .= " exceptionState.throwTypeError(\"The provided value is not of type '${attrType}'.\");\n";
1975 $code .= " exceptionState.throwIfNeeded();\n";
1976 $code .= " return;\n";
1977 $code .= " }\n";
1978 }
1979
1980 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName);
1981 if ($svgNativeType) {
1982 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceNam e);
1983 if ($svgWrappedNativeType =~ /List$/) {
1984 $code .= <<END;
1985 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder());
1986 END
1987 } else {
1988 $code .= " $svgNativeType* wrapper = ${v8ClassName}::toNative(inf o.Holder());\n";
1989 $code .= " if (wrapper->isReadOnly()) {\n";
1990 $code .= " exceptionState.throwDOMException(NoModificationAll owedError, \"The attribute is read-only.\");\n";
1991 $code .= " exceptionState.throwIfNeeded();\n";
1992 $code .= " return;\n";
1993 $code .= " }\n";
1994 $code .= " $svgWrappedNativeType& impInstance = wrapper->property Reference();\n";
1995 $code .= " $svgWrappedNativeType* imp = &impInstance;\n";
1996 }
1997 } elsif ($attrExt->{"OnPrototype"}) {
1998 $code .= <<END;
1999 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
2000 END
2001 } elsif($attrExt->{"PutForwards"}) {
2002 my $destinationAttrName = $attrExt->{"PutForwards"};
2003 my $destinationInterface = ParseInterface($attrType);
2004 die "[PutForwards=x] value must be a wrapper type" unless $destinationIn terface;
2005 my $destinationAttribute = FindAttributeWithName($destinationInterface, $destinationAttrName);
2006 die "[PutForwards=x] could not find $destinationAttrName in interface $a ttrType" unless $destinationAttribute;
2007 $code .= <<END;
2008 ${implClassName}* proxyImp = ${v8ClassName}::toNative(info.Holder());
2009 ${attrType}* imp = proxyImp->${attrName}();
2010 if (!imp)
2011 return;
2012 END
2013 # Override attribute and fall through to forward setter call.
2014 $attribute = $destinationAttribute;
2015 $attrName = $attribute->name;
2016 $attrType = $attribute->type;
2017 $attrExt = $attribute->extendedAttributes;
2018 } else {
2019 my $reflect = $attribute->extendedAttributes->{"Reflect"};
2020 if ($reflect && InheritsInterface($interface, "Node") && $attrType eq "D OMString") {
2021 # Generate super-compact call for regular attribute setter:
2022 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attr Name : $reflect;
2023 my $namespace = NamespaceForAttributeName($interfaceName, $contentAt tributeName);
2024 my $mode = GetV8StringResourceMode($attribute->extendedAttributes);
2025 AddToImplIncludes("${namespace}.h");
2026 $code .= " Element* imp = V8Element::toNative(info.Holder());\n";
2027 $code .= " V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource< $mode>, cppValue, jsValue);\n";
2028 # Attr (not Attribute) used in content attributes
2029 $code .= " imp->setAttribute(${namespace}::${contentAttributeName }Attr, cppValue);\n";
2030 $code .= "}\n";
2031 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2032 $code .= "\n";
2033 $implementation{nameSpaceInternal}->add($code);
2034 return;
2035 # Skip the rest of the function!
2036 }
2037
2038 if (!$attribute->isStatic) {
2039 $code .= <<END;
2040 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
2041 END
2042 }
2043 }
2044
2045 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttribu tes, "parameter");
2046 if ($attribute->type eq "EventHandler") {
2047 if ($interface->name eq "Window") {
2048 $code .= " if (!imp->document())\n";
2049 $code .= " return;\n";
2050 }
2051 } else {
2052 my $asSetterValue = 0;
2053 $code .= JSValueToNativeStatement($attribute->type, $attribute->extended Attributes, $asSetterValue, "jsValue", "cppValue", " ", "info.GetIsolate()");
2054 }
2055
2056 if (IsEnumType($attrType)) {
2057 # setter ignores invalid enumeration values
2058 my @enumValues = ValidEnumValues($attrType);
2059 my @validEqualities = ();
2060 foreach my $enumValue (@enumValues) {
2061 push(@validEqualities, "string == \"$enumValue\"");
2062 }
2063 my $enumValidationExpression = join(" || ", @validEqualities);
2064 $code .= <<END;
2065 String string = cppValue;
2066 if (!($enumValidationExpression))
2067 return;
2068 END
2069 }
2070
2071 my $expression = "cppValue";
2072 my $returnType = $attribute->type;
2073 if (IsRefPtrType($returnType) && !GetArrayType($returnType)) {
2074 $expression = "WTF::getPtr(" . $expression . ")";
2075 }
2076
2077 $code .= GenerateCustomElementInvocationScopeIfNeeded($attribute->extendedAt tributes);
2078
2079 my $returnSvgNativeType = GetSVGTypeNeedingTearOff($returnType);
2080 if ($returnSvgNativeType) {
2081 $code .= <<END;
2082 if (!$expression) {
2083 exceptionState.throwTypeError(\"The provided value is not of type '$retu rnType'.\");
2084 exceptionState.throwIfNeeded();
2085 return;
2086 }
2087 END
2088 $expression = $expression . "->propertyReference()";
2089 }
2090
2091 if ($attribute->type eq "EventHandler") {
2092 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
2093 my $implementedByImplName;
2094 if ($implementedBy) {
2095 $implementedByImplName = GetImplNameFromImplementedBy($implementedBy );
2096 }
2097 if (!InheritsInterface($interface, "Node")) {
2098 my $attrImplName = GetImplName($attribute);
2099 my @arguments;
2100 if ($implementedBy) {
2101 $attrImplName = "${implementedByImplName}::${attrImplName}";
2102 $code .= " ASSERT(imp);\n";
2103 push(@arguments, "*imp");
2104 } else {
2105 $attrImplName = "imp->${attrImplName}";
2106 }
2107 $code .= " moveEventListenerToNewWrapper(info.Holder(), ${attrImp lName}(" . join(", ", @arguments) . "), jsValue, ${v8ClassName}::eventListenerCa cheIndex, info.GetIsolate());\n";
2108 }
2109 my ($functionName, @arguments) = SetterExpression($interfaceName, $attri bute);
2110 if ($implementedBy) {
2111 $code .= " ASSERT(imp);\n";
2112 $functionName = "${implementedByImplName}::${functionName}";
2113 push(@arguments, "*imp");
2114 } else {
2115 $functionName = "imp->${functionName}";
2116 }
2117 if (($interfaceName eq "Window" or $interfaceName eq "WorkerGlobalScope" ) and $attribute->name eq "onerror") {
2118 AddToImplIncludes("bindings/v8/V8ErrorHandler.h");
2119 push(@arguments, "V8EventListenerList::findOrCreateWrapper<V8ErrorHa ndler>(jsValue, true, info.GetIsolate())");
2120 } else {
2121 push(@arguments, "V8EventListenerList::getEventListener(jsValue, tru e, ListenerFindOrCreate)");
2122 }
2123 $code .= " ${functionName}(" . join(", ", @arguments) . ");\n";
2124 } else {
2125 my ($functionName, @arguments) = SetterExpression($interfaceName, $attri bute);
2126 push(@arguments, $expression);
2127 push(@arguments, "exceptionState") if $useExceptions;
2128 if ($attribute->extendedAttributes->{"ImplementedBy"}) {
2129 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy" };
2130 my $implementedByImplName = GetImplNameFromImplementedBy($implemente dBy);
2131 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implement edByImplName));
2132 if (!$attribute->isStatic) {
2133 $code .= " ASSERT(imp);\n";
2134 unshift(@arguments, "*imp");
2135 }
2136 $functionName = "${implementedByImplName}::${functionName}";
2137 } elsif ($attribute->isStatic) {
2138 $functionName = "${implClassName}::${functionName}";
2139 } else {
2140 $functionName = "imp->${functionName}";
2141 }
2142 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{ "SetterCallWith"} || $attribute->extendedAttributes->{"CallWith"}, " ", 1);
2143 $code .= $subCode;
2144 unshift(@arguments, @$arg);
2145 $code .= " ${functionName}(" . join(", ", @arguments) . ");\n";
2146 }
2147
2148 if ($useExceptions) {
2149 $code .= " exceptionState.throwIfNeeded();\n";
2150 }
2151
2152 if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) {
2153 $code .= " if (state.hadException())\n";
2154 $code .= " throwError(state.exception(), info.GetIsolate());\n";
2155 }
2156
2157 if ($svgNativeType) {
2158 if ($useExceptions) {
2159 $code .= " if (!exceptionState.hadException())\n";
2160 $code .= " wrapper->commitChange();\n";
2161 } else {
2162 $code .= " wrapper->commitChange();\n";
2163 }
2164 }
2165
2166 if ($attrCached) {
2167 $code .= <<END;
2168 deleteHiddenValue(info.GetIsolate(), info.Holder(), "${attrName}"); // Inval idate the cached value.
2169 END
2170 }
2171
2172 $code .= "}\n"; # end of setter
2173 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2174 $code .= "\n";
2175 $implementation{nameSpaceInternal}->add($code);
2176 }
2177
2178 sub NullOrOptionalCheck
2179 {
2180 my $parameter = shift;
2181 my $value = shift;
2182
2183 # If undefined is passed for an optional argument, the argument should be
2184 # treated as missing; otherwise undefined is not allowed.
2185 if ($parameter->isNullable) {
2186 if ($parameter->isOptional) {
2187 return "isUndefinedOrNull($value)";
2188 }
2189 return "${value}->IsNull()";
2190 }
2191 if ($parameter->isOptional) {
2192 return "${value}->IsUndefined()";
2193 }
2194 }
2195
2196 sub GenerateParametersCheckExpression
2197 {
2198 my $numParameters = shift;
2199 my $function = shift;
2200
2201 my @andExpression = ();
2202 push(@andExpression, "info.Length() == $numParameters");
2203 my $parameterIndex = 0;
2204 foreach my $parameter (@{$function->parameters}) {
2205 last if $parameterIndex >= $numParameters;
2206 my $value = "info[$parameterIndex]";
2207 my $type = $parameter->type;
2208
2209 my $undefinedOrNullCheck = NullOrOptionalCheck($parameter, $value);
2210
2211 # Only DOMString, wrapper types, and (to some degree) non-wrapper types
2212 # are checked.
2213 #
2214 # FIXME: If distinguishing non-primitive type from primitive type,
2215 # (e.g., sequence<DOMString> from DOMString or Dictionary from double)
2216 # the non-primitive type must appear *first* in the IDL file,
2217 # since we're not adding a check to primitive types.
2218 # This can be avoided if compute overloads for whole overload set at
2219 # once, rather than one method at a time, but that requires a complete
2220 # rewrite of this algorithm.
2221 #
2222 # For DOMString with StrictTypeChecking only Null, Undefined and Object
2223 # are accepted for compatibility. Otherwise, no restrictions are made to
2224 # match the non-overloaded behavior.
2225 #
2226 # FIXME: Implement WebIDL overload resolution algorithm.
2227 # https://code.google.com/p/chromium/issues/detail?id=293561
2228 if ($type eq "DOMString") {
2229 if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
2230 push(@andExpression, "isUndefinedOrNull(${value}) || ${value}->I sString() || ${value}->IsObject()");
2231 }
2232 } elsif (IsCallbackInterface($parameter->type)) {
2233 # For Callbacks only checks if the value is null or function.
2234 push(@andExpression, "${value}->IsNull() || ${value}->IsFunction()") ;
2235 } elsif (GetArrayOrSequenceType($type)) {
2236 if ($parameter->isNullable) {
2237 push(@andExpression, "${value}->IsNull() || ${value}->IsArray()" );
2238 } else {
2239 push(@andExpression, "${value}->IsArray()");
2240 }
2241 } elsif (IsWrapperType($type)) {
2242 if ($parameter->isNullable) {
2243 push(@andExpression, "${value}->IsNull() || V8${type}::hasInstan ce($value, info.GetIsolate())");
2244 } else {
2245 push(@andExpression, "V8${type}::hasInstance($value, info.GetIso late())");
2246 }
2247 } elsif ($nonWrapperTypes{$type}) {
2248 # Non-wrapper types are just objects: we don't distinguish type
2249 if ($undefinedOrNullCheck) {
2250 push(@andExpression, "$undefinedOrNullCheck || ${value}->IsObjec t()");
2251 } else {
2252 push(@andExpression, "${value}->IsObject()");
2253 }
2254 }
2255
2256 $parameterIndex++;
2257 }
2258 @andExpression = map { "($_)" } @andExpression;
2259 my $res = "(" . join(" && ", @andExpression) . ")";
2260 return $res;
2261 }
2262
2263 # As per Web IDL specification, the length of a function Object is
2264 # its number of mandatory parameters.
2265 sub GetFunctionLength
2266 {
2267 my $function = shift;
2268
2269 my $numMandatoryParams = 0;
2270 foreach my $parameter (@{$function->parameters}) {
2271 # Abort as soon as we find the first optional parameter as no mandatory
2272 # parameter can follow an optional one.
2273 last if $parameter->isOptional;
2274 $numMandatoryParams++;
2275 }
2276 return $numMandatoryParams;
2277 }
2278
2279 sub GenerateFunctionParametersCheck
2280 {
2281 my $function = shift;
2282
2283 my @orExpression = ();
2284 my $numParameters = 0;
2285 my $hasVariadic = 0;
2286 my $numMandatoryParams = @{$function->parameters};
2287 foreach my $parameter (@{$function->parameters}) {
2288 if ($parameter->isOptional) {
2289 push(@orExpression, GenerateParametersCheckExpression($numParameters , $function));
2290 $numMandatoryParams--;
2291 }
2292 if ($parameter->isVariadic) {
2293 $hasVariadic = 1;
2294 last;
2295 }
2296 $numParameters++;
2297 }
2298 if (!$hasVariadic) {
2299 push(@orExpression, GenerateParametersCheckExpression($numParameters, $f unction));
2300 }
2301 return ($numMandatoryParams, join(" || ", @orExpression));
2302 }
2303
2304 sub GenerateOverloadedFunction
2305 {
2306 my $function = shift;
2307 my $interface = shift;
2308 my $forMainWorldSuffix = shift;
2309
2310 # Generate code for choosing the correct overload to call. Overloads are
2311 # chosen based on the total number of arguments passed and the type of
2312 # values passed in non-primitive argument slots. When more than a single
2313 # overload is applicable, precedence is given according to the order of
2314 # declaration in the IDL.
2315
2316 my $name = $function->name;
2317 my $interfaceName = $interface->name;
2318 my $implClassName = GetImplName($interface);
2319
2320 my $conditionalString = GenerateConditionalString($function);
2321 my $leastNumMandatoryParams = 255;
2322
2323 my $code = "";
2324 $code .= "#if ${conditionalString}\n\n" if $conditionalString;
2325 $code .= <<END;
2326 static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8 ::Value>& info)
2327 {
2328 END
2329 foreach my $overload (@{$function->{overloads}}) {
2330 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersC heck($overload);
2331 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
2332 $code .= " if ($parametersCheck) {\n";
2333 my $overloadedIndexString = $overload->{overloadIndex};
2334 $code .= " ${name}${overloadedIndexString}Method${forMainWorldSuf fix}(info);\n";
2335 $code .= " return;\n";
2336 $code .= " }\n";
2337 }
2338 if ($leastNumMandatoryParams >= 1) {
2339 $code .= " ExceptionState exceptionState(ExceptionState::ExecutionCon text, \"${name}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
2340 $code .= " if (UNLIKELY(info.Length() < $leastNumMandatoryParams)) {\ n";
2341 $code .= " exceptionState.throwTypeError(ExceptionMessages::notEn oughArguments($leastNumMandatoryParams, info.Length()));\n";
2342 $code .= " exceptionState.throwIfNeeded();\n";
2343 $code .= " return;\n";
2344 $code .= " }\n";
2345 $code .= <<END;
2346 exceptionState.throwTypeError(\"No function was found that matched the signa ture provided.\");
2347 exceptionState.throwIfNeeded();
2348 END
2349 } else {
2350 $code .=<<END;
2351 throwTypeError(ExceptionMessages::failedToExecute(\"${name}\", \"${interface Name}\", \"No function was found that matched the signature provided.\"), info.G etIsolate());
2352 END
2353 }
2354 $code .= "}\n\n";
2355 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
2356 $implementation{nameSpaceInternal}->add($code);
2357 }
2358
2359 sub GenerateFunctionCallback
2360 {
2361 my $function = shift;
2362 my $interface = shift;
2363 my $forMainWorldSuffix = shift;
2364
2365 my $implClassName = GetImplName($interface);
2366 my $v8ClassName = GetV8ClassName($interface);
2367 my $name = $function->name;
2368
2369 if ($name eq "") {
2370 return;
2371 }
2372
2373 my $conditionalString = GenerateConditionalString($function);
2374 my $code = "";
2375 $code .= "#if ${conditionalString}\n" if $conditionalString;
2376 $code .= <<END;
2377 static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbac kInfo<v8::Value>& info)
2378 {
2379 END
2380 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n";
2381 $code .= GenerateFeatureObservation($function->extendedAttributes->{"Measure As"});
2382 $code .= GenerateDeprecationNotification($function->extendedAttributes->{"De precateAs"});
2383 if (HasActivityLogging($forMainWorldSuffix, $function->extendedAttributes, " Access")) {
2384 $code .= GenerateActivityLogging("Method", $interface, "${name}");
2385 }
2386 if (HasCustomMethod($function->extendedAttributes)) {
2387 $code .= " ${v8ClassName}::${name}MethodCustom(info);\n";
2388 } else {
2389 $code .= " ${implClassName}V8Internal::${name}Method${forMainWorldSuf fix}(info);\n";
2390 }
2391 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
2392 $code .= "}\n";
2393 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2394 $code .= "\n";
2395 $implementation{nameSpaceInternal}->add($code);
2396 }
2397
2398 sub GenerateFunction
2399 {
2400 my $function = shift;
2401 my $interface = shift;
2402 my $forMainWorldSuffix = shift;
2403
2404 my $interfaceName = $interface->name;
2405 my $implClassName = GetImplName($interface);
2406 my $v8ClassName = GetV8ClassName($interface);
2407 my $name = $function->name;
2408 my $unoverloadedName = $function->name;
2409 my $implName = GetImplName($function);
2410 my $funcExt = $function->extendedAttributes;
2411
2412 # Add includes for types even if custom
2413 my $returnType = $function->type;
2414 AddIncludesForType($returnType);
2415 foreach my $parameter (@{$function->parameters}) {
2416 my $paramType = $parameter->type;
2417 AddIncludesForType($paramType);
2418 }
2419
2420 if (HasCustomMethod($funcExt) || $name eq "") {
2421 return;
2422 }
2423
2424 if (@{$function->{overloads}} > 1) {
2425 # Append a number to an overloaded method's name to make it unique:
2426 $name = $name . $function->{overloadIndex};
2427 }
2428
2429 my $conditionalString = GenerateConditionalString($function);
2430 my $code = "";
2431 $code .= "#if ${conditionalString}\n" if $conditionalString;
2432 $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionC allbackInfo<v8::Value>& info)\n";
2433 $code .= "{\n";
2434
2435 # We throw exceptions using 'ExceptionState' for a function if:
2436 # - it explicitly claims that exceptions may be raised (or should be if ty pe checks fail.)
2437 # - event listeners.
2438 # - security-checking.
2439 # - weird SVG stuff.
2440 # - takes a parameter that might raise an exception on conversion.
2441 #
2442 my $isEventListener = $name eq "addEventListener" || $name eq "removeEventLi stener";
2443 my $isEventDispatcher = $name eq "dispatchEvent";
2444 my $isSecurityCheckNecessary = $interface->extendedAttributes->{"CheckSecuri ty"} && !$function->extendedAttributes->{"DoNotCheckSecurity"};
2445 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
2446 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty Types($interfaceName);
2447 my $isNonListSVGType = $svgNativeType && !($interfaceName =~ /List$/);
2448
2449 my $hasExceptionState = $raisesExceptions || $isEventListener || $isSecurity CheckNecessary || $isNonListSVGType || HasExceptionRaisingParameter($function);
2450 if ($hasExceptionState) {
2451 $code .= " ExceptionState exceptionState(ExceptionState::ExecutionCon text, \"${unoverloadedName}\", \"${interfaceName}\", info.Holder(), info.GetIsol ate());\n";
2452 }
2453
2454 if ($isEventListener || $isEventDispatcher) {
2455 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2456 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
2457 AddToImplIncludes("core/frame/DOMWindow.h");
2458 $code .= <<END;
2459 EventTarget* impl = ${v8ClassName}::toNative(info.Holder());
2460 if (DOMWindow* window = impl->toDOMWindow()) {
2461 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window ->frame(), exceptionState)) {
2462 exceptionState.throwIfNeeded();
2463 return;
2464 }
2465 if (!window->document())
2466 return;
2467 }
2468 END
2469 }
2470 if ($isEventListener) {
2471 my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only";
2472 my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()";
2473 my $hiddenValueAction = ($name eq "addEventListener") ? "addHiddenValueT oArray" : "removeHiddenValueFromArray";
2474
2475 $code .= <<END;
2476 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(info[ 1], false, ListenerFind${lookupType});
2477 if (listener) {
2478 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, ev entName, info[0]);
2479 impl->${implName}(eventName, listener${passRefPtrHandling}, info[2]->Boo leanValue());
2480 if (!impl->toNode())
2481 ${hiddenValueAction}(info.Holder(), info[1], ${v8ClassName}::eventLi stenerCacheIndex, info.GetIsolate());
2482 }
2483 }
2484 END
2485 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2486 $code .= "\n";
2487 $implementation{nameSpaceInternal}->add($code);
2488 return;
2489 }
2490
2491 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionSta te);
2492
2493 if ($svgNativeType) {
2494 my $nativeClassName = GetNativeType($interfaceName);
2495 if ($interfaceName =~ /List$/) {
2496 $code .= " $nativeClassName imp = ${v8ClassName}::toNative(info.H older());\n";
2497 } else {
2498 AddToImplIncludes("core/dom/ExceptionCode.h");
2499 $code .= " $nativeClassName wrapper = ${v8ClassName}::toNative(in fo.Holder());\n";
2500 $code .= " if (wrapper->isReadOnly()) {\n";
2501 $code .= " exceptionState.throwDOMException(NoModificationAll owedError, \"The object is read-only.\");\n";
2502 $code .= " exceptionState.throwIfNeeded();\n";
2503 $code .= " return;\n";
2504 $code .= " }\n";
2505 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfac eName);
2506 $code .= " $svgWrappedNativeType& impInstance = wrapper->property Reference();\n";
2507 $code .= " $svgWrappedNativeType* imp = &impInstance;\n";
2508 }
2509 } elsif (!$function->isStatic) {
2510 $code .= <<END;
2511 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
2512 END
2513 }
2514
2515 $code .= GenerateCustomElementInvocationScopeIfNeeded($funcExt);
2516
2517 # Check domain security if needed
2518 if ($isSecurityCheckNecessary) {
2519 # We have not find real use cases yet.
2520 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2521 $code .= <<END;
2522 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame (), exceptionState)) {
2523 exceptionState.throwIfNeeded();
2524 return;
2525 }
2526 END
2527 }
2528
2529 if ($function->extendedAttributes->{"CheckSecurity"}) {
2530 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2531 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsol ate(), imp->" . GetImplName($function) . "(exceptionState), exceptionState)) {\n ";
2532 $code .= " v8SetReturnValueNull(info);\n";
2533 $code .= " exceptionState.throwIfNeeded();\n";
2534 $code .= " return;\n";
2535 $code .= " }\n";
2536 END
2537 }
2538
2539 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, $forMainWorldSuffix, $hasExceptionState);
2540 $code .= $parameterCheckString;
2541
2542 # Build the function call string.
2543 $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interfa ce, $forMainWorldSuffix, $hasExceptionState, %replacements);
2544 $code .= "}\n";
2545 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2546 $code .= "\n";
2547 $implementation{nameSpaceInternal}->add($code);
2548 }
2549
2550 sub GenerateCallWith
2551 {
2552 my $callWith = shift;
2553 return ([], "") unless $callWith;
2554 my $indent = shift;
2555 my $returnVoid = shift;
2556 my $function = shift;
2557 my $code = "";
2558
2559 my @callWithArgs;
2560 if (ExtendedAttributeContains($callWith, "ScriptState")) {
2561 $code .= $indent . "ScriptState* currentState = ScriptState::current();\ n";
2562 $code .= $indent . "if (!currentState)\n";
2563 $code .= $indent . " return" . ($returnVoid ? "" : " v8Undefined()") . ";\n";
2564 $code .= $indent . "ScriptState& state = *currentState;\n";
2565 push(@callWithArgs, "&state");
2566 AddToImplIncludes("bindings/v8/ScriptState.h");
2567 }
2568 if (ExtendedAttributeContains($callWith, "ExecutionContext")) {
2569 $code .= $indent . "ExecutionContext* scriptContext = currentExecutionCo ntext(info.GetIsolate());\n";
2570 push(@callWithArgs, "scriptContext");
2571 }
2572 if ($function and ExtendedAttributeContains($callWith, "ScriptArguments")) {
2573 $code .= $indent . "RefPtr<ScriptArguments> scriptArguments(createScript Arguments(info, " . @{$function->parameters} . "));\n";
2574 push(@callWithArgs, "scriptArguments.release()");
2575 AddToImplIncludes("bindings/v8/ScriptCallStackFactory.h");
2576 AddToImplIncludes("core/inspector/ScriptArguments.h");
2577 }
2578 if (ExtendedAttributeContains($callWith, "ActiveWindow")) {
2579 push(@callWithArgs, "callingDOMWindow(info.GetIsolate())");
2580 }
2581 if (ExtendedAttributeContains($callWith, "FirstWindow")) {
2582 push(@callWithArgs, "enteredDOMWindow(info.GetIsolate())");
2583 }
2584 return ([@callWithArgs], $code);
2585 }
2586
2587 sub GenerateArgumentsCountCheck
2588 {
2589 my $function = shift;
2590 my $interface = shift;
2591 my $hasExceptionState = shift;
2592
2593 my $functionName = $function->name;
2594 my $interfaceName = $interface->name;
2595 my $implClassName = GetImplName($interface);
2596
2597 my $isConstructor = $functionName eq "Constructor" || $functionName eq "Name dConstructor";
2598 my $numMandatoryParams = 0;
2599 my $allowNonOptional = 1;
2600 foreach my $param (@{$function->parameters}) {
2601 if ($param->isOptional or $param->isVariadic) {
2602 $allowNonOptional = 0;
2603 } else {
2604 die "An argument must not be declared to be optional unless all subs equent arguments to the operation are also optional." if !$allowNonOptional;
2605 $numMandatoryParams++;
2606 }
2607 }
2608 return "" unless $numMandatoryParams;
2609
2610 my $argumentsCountCheckString = "";
2611 $argumentsCountCheckString .= " if (UNLIKELY(info.Length() < $numMandator yParams)) {\n";
2612 if ($hasExceptionState) {
2613 $argumentsCountCheckString .= " exceptionState.throwTypeError(Exc eptionMessages::notEnoughArguments($numMandatoryParams, info.Length()));\n";
2614 $argumentsCountCheckString .= " exceptionState.throwIfNeeded();\n ";
2615 } elsif ($isConstructor) {
2616 $argumentsCountCheckString .= " throwTypeError(ExceptionMessages: :failedToConstruct(\"$interfaceName\", ExceptionMessages::notEnoughArguments($nu mMandatoryParams, info.Length())), info.GetIsolate());\n";
2617 } else {
2618 $argumentsCountCheckString .= " throwTypeError(ExceptionMessages: :failedToExecute(\"$functionName\", \"$interfaceName\", ExceptionMessages::notEn oughArguments($numMandatoryParams, info.Length())), info.GetIsolate());\n";
2619 }
2620 $argumentsCountCheckString .= " return;\n";
2621 $argumentsCountCheckString .= " }\n";
2622 return $argumentsCountCheckString;
2623 }
2624
2625 sub GenerateParametersCheck
2626 {
2627 my $function = shift;
2628 my $interface = shift;
2629 my $forMainWorldSuffix = shift;
2630 my $hasExceptionState = shift;
2631 my $style = shift || "new";
2632
2633 my $functionName = $function->name;
2634 my $interfaceName = $interface->name;
2635 my $implClassName = GetImplName($interface);
2636
2637 my $parameterCheckString = "";
2638 my $paramIndex = 0;
2639 my %replacements = ();
2640
2641 foreach my $parameter (@{$function->parameters}) {
2642 my $humanFriendlyIndex = $paramIndex + 1;
2643 my $nativeType = GetNativeType($parameter->type, $parameter->extendedAtt ributes, "parameter");
2644
2645 # Optional arguments without [Default=...] should generate an early call with fewer arguments.
2646 # Optional Dictionary arguments always considered to have default of emp ty dictionary.
2647 if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default "} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) {
2648 $parameterCheckString .= <<END;
2649 if (UNLIKELY(info.Length() <= $paramIndex)) {
2650 END
2651 $parameterCheckString .= GenerateFunctionCallString($function, $para mIndex, " " x 2, $interface, $forMainWorldSuffix, $hasExceptionState, %replac ements);
2652 $parameterCheckString .= <<END;
2653 return;
2654 }
2655 END
2656 }
2657
2658 my $parameterName = $parameter->name;
2659 if (IsCallbackInterface($parameter->type)) {
2660 my $v8ClassName = "V8" . $parameter->type;
2661 AddToImplIncludes("$v8ClassName.h");
2662 if ($parameter->isOptional) {
2663 $parameterCheckString .= " OwnPtr<" . $parameter->type . "> $ parameterName;\n";
2664 $parameterCheckString .= " if (info.Length() > $paramIndex && !isUndefinedOrNull(info[$paramIndex])) {\n";
2665 $parameterCheckString .= " if (!info[$paramIndex]->IsFunc tion()) {\n";
2666 if ($hasExceptionState) {
2667 $parameterCheckString .= " exceptionState.throwTy peError(\"The callback provided as parameter $humanFriendlyIndex is not a functi on.\");\n";
2668 $parameterCheckString .= " exceptionState.throwIf Needed();\n";
2669 } else {
2670 $parameterCheckString .= " throwTypeError(Excepti onMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"The callbac k provided as parameter $humanFriendlyIndex is not a function.\"), info.GetIsola te());\n";
2671 }
2672 $parameterCheckString .= " return;\n";
2673 $parameterCheckString .= " }\n";
2674 $parameterCheckString .= " $parameterName = ${v8ClassName }::create(v8::Handle<v8::Function>::Cast(info[$paramIndex]), currentExecutionCon text(info.GetIsolate()));\n";
2675 $parameterCheckString .= " }\n";
2676 } else {
2677 $parameterCheckString .= " if (info.Length() <= $paramIndex | | ";
2678 if ($parameter->isNullable) {
2679 $parameterCheckString .= "!(info[$paramIndex]->IsFunction() || info[$paramIndex]->IsNull())";
2680 } else {
2681 $parameterCheckString .= "!info[$paramIndex]->IsFunction()";
2682 }
2683 $parameterCheckString .= ") {\n";
2684 if ($hasExceptionState) {
2685 $parameterCheckString .= " exceptionState.throwTypeEr ror(\"The callback provided as parameter $humanFriendlyIndex is not a function.\ ");\n";
2686 $parameterCheckString .= " exceptionState.throwIfNeed ed();\n";
2687 } else {
2688 $parameterCheckString .= " throwTypeError(ExceptionMe ssages::failedToExecute(\"$functionName\", \"$interfaceName\", \"The callback pr ovided as parameter $humanFriendlyIndex is not a function.\"), info.GetIsolate() );\n";
2689 }
2690 $parameterCheckString .= " return;\n";
2691 $parameterCheckString .= " }\n";
2692 $parameterCheckString .= " OwnPtr<" . $parameter->type . "> $ parameterName = ";
2693 $parameterCheckString .= "info[$paramIndex]->IsNull() ? nullptr : " if $parameter->isNullable;
2694 $parameterCheckString .= "${v8ClassName}::create(v8::Handle<v8:: Function>::Cast(info[$paramIndex]), currentExecutionContext(info.GetIsolate())); \n";
2695 }
2696 } elsif ($parameter->extendedAttributes->{"Clamp"}) {
2697 my $nativeValue = "${parameterName}NativeValue";
2698 my $idlType = $parameter->type;
2699 $parameterCheckString .= " $nativeType $parameterName = 0;\n" ;
2700 $parameterCheckString .= " V8TRYCATCH_VOID(double, $nativeVal ue, info[$paramIndex]->NumberValue());\n";
2701 $parameterCheckString .= " if (!std::isnan($nativeValue))\n";
2702 $parameterCheckString .= " $parameterName = clampTo<$idlT ype>($nativeValue);\n";
2703 } elsif ($parameter->type eq "SerializedScriptValue") {
2704 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
2705 $parameterCheckString .= " $nativeType $parameterName = Serialize dScriptValue::create(info[$paramIndex], 0, 0, exceptionState, info.GetIsolate()) ;\n";
2706 $parameterCheckString .= " if (exceptionState.throwIfNeeded())\n" ;
2707 $parameterCheckString .= " return;\n";
2708 } elsif ($parameter->isVariadic) {
2709 my $nativeElementType = GetNativeType($parameter->type);
2710 if ($nativeElementType =~ />$/) {
2711 $nativeElementType .= " ";
2712 }
2713
2714 my $argType = $parameter->type;
2715 if (IsWrapperType($argType)) {
2716 $parameterCheckString .= " Vector<$nativeElementType> $parame terName;\n";
2717 $parameterCheckString .= " for (int i = $paramIndex; i < info .Length(); ++i) {\n";
2718 $parameterCheckString .= " if (!V8${argType}::hasInstance (info[i], info.GetIsolate())) {\n";
2719 if ($hasExceptionState) {
2720 $parameterCheckString .= " exceptionState.throwTy peError(\"parameter $humanFriendlyIndex is not of type \'$argType\'.\");\n";
2721 $parameterCheckString .= " exceptionState.throwIf Needed();\n";
2722 } else {
2723 $parameterCheckString .= " throwTypeError(Excepti onMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $ humanFriendlyIndex is not of type \'$argType\'.\"), info.GetIsolate());\n";
2724 }
2725 $parameterCheckString .= " return;\n";
2726 $parameterCheckString .= " }\n";
2727 $parameterCheckString .= " $parameterName.append(V8${argT ype}::toNative(v8::Handle<v8::Object>::Cast(info[i])));\n";
2728 $parameterCheckString .= " }\n";
2729 } else {
2730 $parameterCheckString .= " V8TRYCATCH_VOID(Vector<$nativeElem entType>, $parameterName, toNativeArguments<$nativeElementType>(info, $paramInde x));\n";
2731 }
2732 } elsif ($nativeType =~ /^V8StringResource/) {
2733 my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : "";
2734 my $jsValue = $parameter->isOptional && $default eq "NullString" ? " argumentOrNull(info, $paramIndex)" : "info[$paramIndex]";
2735 my $stringResourceParameterName = $parameterName;
2736 my $isNullable = IsNullableParameter($parameter);
2737 if ($isNullable) {
2738 $parameterCheckString .= " bool ${parameterName}IsNull = $jsV alue->IsNull();\n";
2739 $stringResourceParameterName .= "StringResource";
2740 }
2741 $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $humanFriendlyIndex, $jsValue, $stringResourcePa rameterName, " ", "info.GetIsolate()");
2742 $parameterCheckString .= " String $parameterName = $stringResourc eParameterName;\n" if $isNullable;
2743 if (IsEnumType($parameter->type)) {
2744 my @enumValues = ValidEnumValues($parameter->type);
2745 my @validEqualities = ();
2746 foreach my $enumValue (@enumValues) {
2747 push(@validEqualities, "string == \"$enumValue\"");
2748 }
2749 my $enumValidationExpression = join(" || ", @validEqualities);
2750 $parameterCheckString .= " String string = $parameterName;\n ";
2751 $parameterCheckString .= " if (!($enumValidationExpression)) {\n";
2752 if ($hasExceptionState) {
2753 $parameterCheckString .= " exceptionState.throwTypeEr ror(\"parameter $humanFriendlyIndex (\'\" + string + \"\') is not a valid enum v alue.\");\n";
2754 $parameterCheckString .= " exceptionState.throwIfNeed ed();\n";
2755 } else {
2756 $parameterCheckString .= " throwTypeError(ExceptionMe ssages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $huma nFriendlyIndex (\'\" + string + \"\') is not a valid enum value.\"), info.GetIso late());\n";
2757 }
2758 $parameterCheckString .= " return;\n";
2759 $parameterCheckString .= " }\n";
2760 }
2761 } else {
2762 # If the [StrictTypeChecking] extended attribute is present, type
2763 # check interface type arguments for correct type and nullability.
2764 #
2765 # If the argument is passed, and is not |undefined| or |null|, then
2766 # it must implement the interface type, otherwise throw a TypeError
2767 # If the parameter is nullable, then both |undefined| and |null|
2768 # pass a NULL pointer to the C++ code, otherwise these also throw.
2769 # Without [StrictTypeChecking], in all these cases NULL is silently
2770 # passed to the C++ code.
2771 #
2772 # Per the Web IDL and ECMAScript specifications, incoming values
2773 # can always be converted to primitive types and strings (including
2774 # |undefined| and |null|), so do not throw TypeError for these.
2775 if ($function->extendedAttributes->{"StrictTypeChecking"} || $interf ace->extendedAttributes->{"StrictTypeChecking"}) {
2776 my $argValue = "info[$paramIndex]";
2777 my $argType = $parameter->type;
2778 if (IsWrapperType($argType)) {
2779 my $undefinedNullCheck = $parameter->isNullable ? " !isUndef inedOrNull($argValue) &&" : "";
2780 $parameterCheckString .= " if (info.Length() > $paramInde x &&$undefinedNullCheck !V8${argType}::hasInstance($argValue, info.GetIsolate()) ) {\n";
2781 if ($hasExceptionState) {
2782 $parameterCheckString .= " exceptionState.throwTy peError(\"parameter $humanFriendlyIndex is not of type \'$argType\'.\");\n";
2783 $parameterCheckString .= " exceptionState.throwIf Needed();\n";
2784 }else {
2785 $parameterCheckString .= " throwTypeError(Excepti onMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $ humanFriendlyIndex is not of type \'$argType\'.\"), info.GetIsolate());\n";
2786 }
2787 $parameterCheckString .= " return;\n";
2788 $parameterCheckString .= " }\n";
2789 }
2790 }
2791 my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : "";
2792 my $jsValue = $parameter->isOptional && $default eq "NullString" ? " argumentOrNull(info, $paramIndex)" : "info[$paramIndex]";
2793 my $isNullable = IsNullableParameter($parameter);
2794 $parameterCheckString .= " bool ${parameterName}IsNull = $jsValue ->IsNull();\n" if $isNullable;
2795 $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $humanFriendlyIndex, $jsValue, $parameterName, " ", "info.GetIsolate()");
2796 if ($nativeType eq 'Dictionary' or $nativeType eq 'ScriptPromise') {
2797 $parameterCheckString .= " if (!$parameterName.isUndefinedOrN ull() && !$parameterName.isObject()) {\n";
2798 if ($hasExceptionState) {
2799 $parameterCheckString .= " exceptionState.throwTypeEr ror(\"parameter ${humanFriendlyIndex} ('${parameterName}') is not an object.\"); \n";
2800 $parameterCheckString .= " exceptionState.throwIfNeed ed();\n";
2801 } elsif ($functionName eq "Constructor") {
2802 $parameterCheckString .= " throwTypeError(ExceptionMe ssages::failedToConstruct(\"$interfaceName\", \"parameter ${humanFriendlyIndex} ('${parameterName}') is not an object.\"), info.GetIsolate());\n";
2803 } else {
2804 $parameterCheckString .= " throwTypeError(ExceptionMe ssages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter ${hum anFriendlyIndex} ('${parameterName}') is not an object.\"), info.GetIsolate());\ n";
2805 }
2806 $parameterCheckString .= " return;\n";
2807 $parameterCheckString .= " }\n";
2808 }
2809 }
2810
2811 $paramIndex++;
2812 }
2813 return ($parameterCheckString, $paramIndex, %replacements);
2814 }
2815
2816 sub GenerateOverloadedConstructorCallback
2817 {
2818 my $interface = shift;
2819 my $interfaceName = $interface->name;
2820 my $implClassName = GetImplName($interface);
2821
2822 my $code .= <<END;
2823 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info)
2824 {
2825 END
2826 my $leastNumMandatoryParams = 255;
2827 foreach my $constructor (@{$interface->constructors}) {
2828 my $name = "constructor" . $constructor->overloadedIndex;
2829 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersC heck($constructor);
2830 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
2831 $code .= " if ($parametersCheck) {\n";
2832 $code .= " ${implClassName}V8Internal::${name}(info);\n";
2833 $code .= " return;\n";
2834 $code .= " }\n";
2835 }
2836 if ($leastNumMandatoryParams >= 1) {
2837 $code .= <<END;
2838 ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${inter faceName}\", info.Holder(), info.GetIsolate());
2839 if (UNLIKELY(info.Length() < $leastNumMandatoryParams)) {
2840 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments($lea stNumMandatoryParams, info.Length()));
2841 exceptionState.throwIfNeeded();
2842 return;
2843 }
2844 exceptionState.throwTypeError(\"No matching constructor signature.\");
2845 exceptionState.throwIfNeeded();
2846 END
2847 } else {
2848 $code .= <<END;
2849 throwTypeError(ExceptionMessages::failedToConstruct(\"${interfaceName}\", \" No matching constructor signature.\"), info.GetIsolate());
2850 END
2851 }
2852 $code .= "}\n\n";
2853 $implementation{nameSpaceInternal}->add($code);
2854 }
2855
2856 sub GenerateSingleConstructorCallback
2857 {
2858 my $interface = shift;
2859 my $function = shift;
2860
2861 my $interfaceName = $interface->name;
2862 my $implClassName = GetImplName($interface);
2863 my $v8ClassName = GetV8ClassName($interface);
2864 my $overloadedIndexString = "";
2865 if ($function->overloadedIndex > 0) {
2866 $overloadedIndexString .= $function->overloadedIndex;
2867 }
2868
2869 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor" ;
2870 my $hasExceptionState = $function->extendedAttributes->{"RaisesException"} | | $constructorRaisesException || HasExceptionRaisingParameter($function);
2871
2872 my @beforeArgumentList;
2873 my @afterArgumentList;
2874 my $code = "";
2875 $code .= <<END;
2876 static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v 8::Value>& info)
2877 {
2878 END
2879
2880 if ($hasExceptionState) {
2881 $code .= " ExceptionState exceptionState(ExceptionState::Construction Context, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
2882 }
2883 if ($function->overloadedIndex == 0) {
2884 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptio nState);
2885 }
2886
2887 # FIXME: Currently [Constructor(...)] does not yet support optional argument s without [Default=...]
2888 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, "", $hasExceptionState);
2889 $code .= $parameterCheckString;
2890
2891 if ($interface->extendedAttributes->{"ConstructorCallWith"}) {
2892 if (ExtendedAttributeContains($interface->extendedAttributes->{"Construc torCallWith"}, "ExecutionContext")) {
2893 push(@beforeArgumentList, "context");
2894 $code .= " ExecutionContext* context = currentExecutionContext(in fo.GetIsolate());\n";
2895 }
2896 if (ExtendedAttributeContains($interface->extendedAttributes->{"Construc torCallWith"}, "Document")) {
2897 push(@beforeArgumentList, "document");
2898 $code .= " Document& document = *toDocument(currentExecutionConte xt(info.GetIsolate()));\n";
2899 }
2900 }
2901
2902 if ($constructorRaisesException) {
2903 push(@afterArgumentList, "exceptionState");
2904 }
2905
2906 my @argumentList;
2907 my $index = 0;
2908 foreach my $parameter (@{$function->parameters}) {
2909 last if $index eq $paramIndex;
2910 if ($replacements{$parameter->name}) {
2911 push(@argumentList, $replacements{$parameter->name});
2912 } else {
2913 push(@argumentList, $parameter->name);
2914 }
2915 $index++;
2916 }
2917
2918 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterAr gumentList);
2919 my $refPtrType = IsWillBeGarbageCollectedType($interfaceName) ? "RefPtrWillB eRawPtr<$implClassName>" : "RefPtr<$implClassName>";
2920 $code .= " $refPtrType impl = ${implClassName}::create(${argumentString}) ;\n";
2921 $code .= " v8::Handle<v8::Object> wrapper = info.Holder();\n";
2922
2923 if ($constructorRaisesException) {
2924 $code .= " if (exceptionState.throwIfNeeded())\n";
2925 $code .= " return;\n";
2926 }
2927
2928 $code .= <<END;
2929
2930 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${ v8ClassName}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration: :Dependent);
2931 v8SetReturnValue(info, wrapper);
2932 }
2933
2934 END
2935 $implementation{nameSpaceInternal}->add($code);
2936 }
2937
2938 # The Web IDL specification states that Interface objects for interfaces MUST ha ve a property named
2939 # "length" that returns the length of the shortest argument list of the entries in the effective
2940 # overload set for constructors. In other words, use the lowest number of mandat ory arguments among
2941 # all constructors.
2942 sub GetInterfaceLength
2943 {
2944 my $interface = shift;
2945
2946 my $leastConstructorLength = 0;
2947 if ($interface->extendedAttributes->{"EventConstructor"}) {
2948 $leastConstructorLength = 1;
2949 } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->exte ndedAttributes->{"CustomConstructor"}) {
2950 my @constructors = @{$interface->constructors};
2951 my @customConstructors = @{$interface->customConstructors};
2952 $leastConstructorLength = 255;
2953 foreach my $constructor (@constructors, @customConstructors) {
2954 my $constructorLength = GetFunctionLength($constructor);
2955 $leastConstructorLength = $constructorLength if ($constructorLength < $leastConstructorLength);
2956 }
2957 }
2958
2959 return $leastConstructorLength;
2960 }
2961
2962 sub GenerateConstructorCallback
2963 {
2964 my $interface = shift;
2965
2966 my $implClassName = GetImplName($interface);
2967 my $v8ClassName = GetV8ClassName($interface);
2968 my $code = "";
2969 $code .= "void ${v8ClassName}::constructorCallback(const v8::FunctionCallbac kInfo<v8::Value>& info)\n";
2970 $code .= "{\n";
2971 $code .= " TRACE_EVENT_SCOPED_SAMPLING_STATE(\"Blink\", \"DOMConstructor\ ");\n";
2972 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"Measur eAs"});
2973 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"D eprecateAs"});
2974 $code .= GenerateConstructorHeader($interface->name);
2975 if (HasCustomConstructor($interface)) {
2976 $code .= " ${v8ClassName}::constructorCustom(info);\n";
2977 } else {
2978 $code .= " ${implClassName}V8Internal::constructor(info);\n";
2979 }
2980 $code .= "}\n\n";
2981 $implementation{nameSpaceWebCore}->add($code);
2982 }
2983
2984 sub GenerateConstructor
2985 {
2986 my $interface = shift;
2987
2988 if (@{$interface->constructors} == 1) {
2989 GenerateSingleConstructorCallback($interface, @{$interface->constructors }[0]);
2990 } else {
2991 foreach my $constructor (@{$interface->constructors}) {
2992 GenerateSingleConstructorCallback($interface, $constructor);
2993 }
2994 GenerateOverloadedConstructorCallback($interface);
2995 }
2996 }
2997
2998 sub GenerateEventConstructor
2999 {
3000 my $interface = shift;
3001
3002 my $interfaceName = $interface->name;
3003 my $implClassName = GetImplName($interface);
3004 my $v8ClassName = GetV8ClassName($interface);
3005
3006 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor" ;
3007
3008 my @anyAttributeNames;
3009 foreach my $attribute (@{$interface->attributes}) {
3010 if ($attribute->type eq "any") {
3011 push(@anyAttributeNames, $attribute->name);
3012 }
3013 }
3014
3015 AddToImplIncludes("bindings/v8/Dictionary.h");
3016 $implementation{nameSpaceInternal}->add(<<END);
3017 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info)
3018 {
3019 ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${inter faceName}\", info.Holder(), info.GetIsolate());
3020 if (info.Length() < 1) {
3021 exceptionState.throwTypeError("An event name must be provided.");
3022 exceptionState.throwIfNeeded();
3023 return;
3024 }
3025
3026 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]);
3027 END
3028
3029 foreach my $attrName (@anyAttributeNames) {
3030 $implementation{nameSpaceInternal}->add(" v8::Local<v8::Value> ${attr Name};\n");
3031 }
3032
3033 $implementation{nameSpaceInternal}->add(<<END);
3034 ${implClassName}Init eventInit;
3035 if (info.Length() >= 2) {
3036 V8TRYCATCH_VOID(Dictionary, options, Dictionary(info[1], info.GetIsolate ()));
3037 if (!initialize${implClassName}(eventInit, options, exceptionState, info )) {
3038 exceptionState.throwIfNeeded();
3039 return;
3040 }
3041 END
3042
3043 # Store 'any'-typed properties on the wrapper to avoid leaking them between isolated worlds.
3044 foreach my $attrName (@anyAttributeNames) {
3045 $implementation{nameSpaceInternal}->add(<<END);
3046 options.get("${attrName}", ${attrName});
3047 if (!${attrName}.IsEmpty())
3048 setHiddenValue(info.GetIsolate(), info.Holder(), "${attrName}", ${at trName});
3049 END
3050 }
3051
3052 $implementation{nameSpaceInternal}->add(<<END);
3053 }
3054 END
3055
3056 my $exceptionStateArgument = "";
3057 if ($constructorRaisesException) {
3058 ${exceptionStateArgument} = ", exceptionState";
3059 }
3060
3061 $implementation{nameSpaceInternal}->add(<<END);
3062 RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit${e xceptionStateArgument});
3063 END
3064
3065 if ($constructorRaisesException) {
3066 $implementation{nameSpaceInternal}->add(<<END);
3067 if (exceptionState.throwIfNeeded())
3068 return;
3069 END
3070 }
3071
3072 if (@anyAttributeNames) {
3073 # Separate check to simplify Python code
3074 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
3075 }
3076 if (@anyAttributeNames && $interface->name ne 'ErrorEvent') {
3077 # If we're in an isolated world, create a SerializedScriptValue and
3078 # store it in the event for later cloning if the property is accessed
3079 # from another world.
3080 # The main world case is handled lazily (in Custom code).
3081 #
3082 # We do not clone Error objects (exceptions), for 2 reasons:
3083 # 1) Errors carry a reference to the isolated world's global object,
3084 # and thus passing it around would cause leakage.
3085 # 2) Errors cannot be cloned (or serialized):
3086 # http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom -interfaces.html#safe-passing-of-structured-data
3087 $implementation{nameSpaceInternal}->add(" if (DOMWrapperWorld::curren t(info.GetIsolate())->isIsolatedWorld()) {\n");
3088 foreach my $attrName (@anyAttributeNames) {
3089 my $setter = "setSerialized" . FirstLetterToUpperCase($attrName);
3090 $implementation{nameSpaceInternal}->add(<<END);
3091 if (!${attrName}.IsEmpty())
3092 event->${setter}(SerializedScriptValue::createAndSwallowExceptions($ {attrName}, info.GetIsolate()));
3093 END
3094 }
3095 $implementation{nameSpaceInternal}->add(" }\n\n");
3096 }
3097
3098 $implementation{nameSpaceInternal}->add(<<END);
3099 v8::Handle<v8::Object> wrapper = info.Holder();
3100 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(event.release(), &$ {v8ClassName}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration ::Dependent);
3101 v8SetReturnValue(info, wrapper);
3102 }
3103
3104 END
3105
3106 my $code = "";
3107 $code .= <<END;
3108 bool initialize${implClassName}(${implClassName}Init& eventInit, const Dictionar y& options, ExceptionState& exceptionState, const v8::FunctionCallbackInfo<v8::V alue>& info, const String& forEventName)
3109 {
3110 Dictionary::ConversionContext conversionContext(forEventName.isEmpty() ? Str ing("${interfaceName}") : forEventName, "", exceptionState);
3111 END
3112
3113 if ($interface->parent) {
3114 my $interfaceBase = $interface->parent;
3115 $code .= <<END;
3116 if (!initialize${interfaceBase}(eventInit, options, exceptionState, info, fo rEventName.isEmpty() ? String("${interfaceName}") : forEventName))
3117 return false;
3118
3119 END
3120 }
3121
3122 foreach my $attribute (@{$interface->attributes}) {
3123 if ($attribute->extendedAttributes->{"InitializedByEventConstructor"}) {
3124 if ($attribute->type ne "any") {
3125 my $attributeName = $attribute->name;
3126 my $attributeImplName = GetImplName($attribute);
3127
3128 my $isNullable = $attribute->isNullable ? "true" : "false";
3129 my $dictionaryGetter = "options.convert(conversionContext.setCon versionType(\"" . $attribute->type . "\", $isNullable), \"$attributeName\", even tInit.$attributeImplName)";
3130 my $deprecation = $attribute->extendedAttributes->{"DeprecateAs" };
3131 if ($deprecation) {
3132 $code .= " if ($dictionaryGetter) {\n";
3133 $code .= " if (options.hasProperty(\"$attributeName\" ))\n";
3134 $code .= " " . GenerateDeprecationNotification($depre cation);
3135 $code .= " } else {\n";
3136 $code .= " return false;\n";
3137 $code .= " }\n";
3138 } else {
3139 $code .= " if (!$dictionaryGetter)\n";
3140 $code .= " return false;\n";
3141 }
3142 }
3143 }
3144 }
3145
3146 $code .= <<END;
3147 return true;
3148 }
3149
3150 END
3151 $implementation{nameSpaceWebCore}->add($code);
3152 }
3153
3154 sub GenerateNamedConstructor
3155 {
3156 my $function = shift;
3157 my $interface = shift;
3158
3159 my $interfaceName = $interface->name;
3160 my $implClassName = GetImplName($interface);
3161 my $v8ClassName = GetV8ClassName($interface);
3162 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor" ;
3163 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"} || $constructorRaisesException || HasExceptionRaisingParameter($function);
3164
3165 my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttr ibutes->{"MeasureAs"});
3166 my $maybeDeprecateFeature = GenerateDeprecationNotification($function->exten dedAttributes->{"DeprecateAs"});
3167
3168 my @beforeArgumentList;
3169 my @afterArgumentList;
3170
3171 my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObje ct") ? "${v8ClassName}::toActiveDOMObject" : "0";
3172 my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8Clas sName}::toEventTarget" : "0";
3173 my $derefObject = "${v8ClassName}::derefObject";
3174 my $isGarbageCollected = IsWillBeGarbageCollectedType($interfaceName) ? "tru e" : "false";
3175
3176 $implementation{nameSpaceWebCore}->add(<<END);
3177 const WrapperTypeInfo ${v8ClassName}Constructor::wrapperTypeInfo = { gin::kEmbed derBlink, ${v8ClassName}Constructor::domTemplate, $derefObject, $toActiveDOMObje ct, $toEventTarget, 0, ${v8ClassName}::installPerContextEnabledMethods, 0, Wrapp erTypeObjectPrototype, $isGarbageCollected };
3178
3179 END
3180
3181 my $code = "";
3182 $code .= <<END;
3183 static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8: :Value>& info)
3184 {
3185 END
3186 $code .= $maybeObserveFeature if $maybeObserveFeature;
3187 $code .= $maybeDeprecateFeature if $maybeDeprecateFeature;
3188 $code .= GenerateConstructorHeader($function->extendedAttributes->{"NamedCon structor"});
3189 $code .= <<END;
3190 Document* document = currentDocument(info.GetIsolate());
3191 ASSERT(document);
3192
3193 // Make sure the document is added to the DOM Node map. Otherwise, the ${imp lClassName} instance
3194 // may end up being the only node in the map and get garbage-collected prema turely.
3195 toV8(document, info.Holder(), info.GetIsolate());
3196
3197 END
3198
3199 my $hasExceptionState = $raisesExceptions;
3200 if ($hasExceptionState) {
3201 $code .= " ExceptionState exceptionState(ExceptionState::Construction Context, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
3202 }
3203 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionSta te);
3204
3205 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, "", $hasExceptionState);
3206 $code .= $parameterCheckString;
3207
3208 push(@beforeArgumentList, "*document");
3209
3210 if ($constructorRaisesException) {
3211 push(@afterArgumentList, "exceptionState");
3212 }
3213
3214 my @argumentList;
3215 my $index = 0;
3216 foreach my $parameter (@{$function->parameters}) {
3217 last if $index eq $paramIndex;
3218 if ($replacements{$parameter->name}) {
3219 push(@argumentList, $replacements{$parameter->name});
3220 } else {
3221 push(@argumentList, $parameter->name);
3222 }
3223 $index++;
3224 }
3225
3226 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterAr gumentList);
3227 $code .= " RefPtr<${implClassName}> impl = ${implClassName}::createForJSC onstructor(${argumentString});\n";
3228 $code .= " v8::Handle<v8::Object> wrapper = info.Holder();\n";
3229
3230 if ($constructorRaisesException) {
3231 $code .= " if (exceptionState.throwIfNeeded())\n";
3232 $code .= " return;\n";
3233 }
3234
3235 $code .= <<END;
3236
3237 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${ v8ClassName}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperCon figuration::Dependent);
3238 v8SetReturnValue(info, wrapper);
3239 }
3240
3241 END
3242 $implementation{nameSpaceWebCore}->add($code);
3243
3244 $code = <<END;
3245 v8::Handle<v8::FunctionTemplate> ${v8ClassName}Constructor::domTemplate(v8::Isol ate* isolate, WrapperWorldType currentWorldType)
3246 {
3247 static int domTemplateKey; // This address is used for a key to look up the dom template.
3248 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
3249 v8::Local<v8::FunctionTemplate> result = data->existingDOMTemplate(currentWo rldType, &domTemplateKey);
3250 if (!result.IsEmpty())
3251 return result;
3252
3253 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
3254 v8::EscapableHandleScope scope(isolate);
3255 result = v8::FunctionTemplate::New(isolate, ${v8ClassName}ConstructorCallbac k);
3256
3257 v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate();
3258 instanceTemplate->SetInternalFieldCount(${v8ClassName}::internalFieldCount);
3259 result->SetClassName(v8AtomicString(isolate, "${implClassName}"));
3260 result->Inherit(${v8ClassName}::domTemplate(isolate, currentWorldType));
3261 data->setDOMTemplate(currentWorldType, &domTemplateKey, result);
3262
3263 return scope.Escape(result);
3264 }
3265
3266 END
3267 $implementation{nameSpaceWebCore}->add($code);
3268 }
3269
3270 sub GenerateConstructorHeader
3271 {
3272 my $constructorName = shift;
3273
3274 AddToImplIncludes("bindings/v8/V8ObjectConstructor.h");
3275 my $content = <<END;
3276 if (!info.IsConstructCall()) {
3277 throwTypeError(ExceptionMessages::failedToConstruct("$constructorName", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate());
3278 return;
3279 }
3280
3281 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
3282 v8SetReturnValue(info, info.Holder());
3283 return;
3284 }
3285
3286 END
3287 return $content;
3288 }
3289
3290 sub GenerateAttributeConfigurationArray
3291 {
3292 my $interface = shift;
3293 my $attributes = shift;
3294 my $exposeJSAccessors = shift;
3295
3296 my $code = "";
3297 foreach my $attribute (@$attributes) {
3298 my $conditionalString = GenerateConditionalString($attribute);
3299 my $subCode = "";
3300 $subCode .= "#if ${conditionalString}\n" if $conditionalString;
3301 $subCode .= GenerateAttributeConfiguration($interface, $attribute, ",", "", $exposeJSAccessors);
3302 $subCode .= "#endif // ${conditionalString}\n" if $conditionalString;
3303 $code .= $subCode;
3304 }
3305 return $code;
3306 }
3307
3308 sub GenerateAttributeConfigurationParameters
3309 {
3310 my $interface = shift;
3311 my $attribute = shift;
3312 my $attrName = $attribute->name;
3313 my $attrExt = $attribute->extendedAttributes;
3314 my $implClassName = GetImplName($interface);
3315
3316 my @accessControlList;
3317 if (my $doNotCheckSecurity = $attrExt->{"DoNotCheckSecurity"}) {
3318 if ($doNotCheckSecurity eq "Getter") {
3319 push(@accessControlList, "v8::ALL_CAN_READ");
3320 } elsif ($doNotCheckSecurity eq "Setter") {
3321 push(@accessControlList, "v8::ALL_CAN_WRITE");
3322 } else {
3323 push(@accessControlList, "v8::ALL_CAN_READ");
3324 if (!IsReadonly($attribute)) {
3325 push(@accessControlList, "v8::ALL_CAN_WRITE");
3326 }
3327 }
3328 }
3329 if ($attrExt->{"Unforgeable"}) {
3330 push(@accessControlList, "v8::PROHIBITS_OVERWRITING");
3331 }
3332 @accessControlList = ("v8::DEFAULT") unless @accessControlList;
3333 my $accessControl = "static_cast<v8::AccessControl>(" . join(" | ", @accessC ontrolList) . ")";
3334
3335 my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attribute ) || "";
3336 if ($customAccessor eq "VALUE_IS_MISSING") {
3337 # use the naming convension, interface + (capitalize) attr name
3338 $customAccessor = $implClassName . "::" . $attrName;
3339 }
3340
3341 my $getter;
3342 my $setter;
3343 my $getterForMainWorld;
3344 my $setterForMainWorld;
3345
3346 my $isConstructor = ($attribute->type =~ /Constructor$/);
3347
3348 # Check attributes.
3349 # As per Web IDL specification, constructor properties on the ECMAScript glo bal object should be
3350 # configurable and should not be enumerable.
3351 my @propAttributeList;
3352 if ($attrExt->{"NotEnumerable"} || $isConstructor) {
3353 push(@propAttributeList, "v8::DontEnum");
3354 }
3355 if ($attrExt->{"Unforgeable"} && !$isConstructor) {
3356 push(@propAttributeList, "v8::DontDelete");
3357 }
3358 @propAttributeList = ("v8::None") unless @propAttributeList;
3359 my $propAttribute = join(" | ", @propAttributeList);
3360
3361 my $onProto = "0 /* on instance */";
3362 my $data = "0"; # no data
3363
3364 # Constructor
3365 if ($isConstructor) {
3366 my $constructorType = $attribute->type;
3367 $constructorType =~ s/Constructor$//;
3368
3369 # For NamedConstructors we do not generate a header file. The code for t he NamedConstructor
3370 # gets generated when we generate the code for its interface.
3371 if ($constructorType !~ /Constructor$/) {
3372 AddToImplIncludes("V8${constructorType}.h");
3373 }
3374 $data = "const_cast<WrapperTypeInfo*>(&V8${constructorType}::wrapperType Info)";
3375 $getter = "${implClassName}V8Internal::${implClassName}ConstructorGetter ";
3376 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttrib uteSetterCallback";
3377 $getterForMainWorld = "0";
3378 $setterForMainWorld = "0";
3379 } else {
3380 # Default Getter and Setter
3381 $getter = "${implClassName}V8Internal::${attrName}AttributeGetterCallbac k";
3382 $setter = "${implClassName}V8Internal::${attrName}AttributeSetterCallbac k";
3383 $getterForMainWorld = "${getter}ForMainWorld";
3384 $setterForMainWorld = "${setter}ForMainWorld";
3385
3386 if (!HasCustomSetter($attribute) && !$attrExt->{"PutForwards"} && $attrE xt->{"Replaceable"}) {
3387 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAt tributeSetterCallback";
3388 $setterForMainWorld = "0";
3389 }
3390 }
3391
3392 # Read only attributes
3393 if (IsReadonly($attribute)) {
3394 $setter = "0";
3395 $setterForMainWorld = "0";
3396 }
3397
3398 # An accessor can be installed on the prototype
3399 if ($attrExt->{"OnPrototype"}) {
3400 $onProto = "1 /* on prototype */";
3401 }
3402
3403 if (!$attrExt->{"PerWorldBindings"}) {
3404 $getterForMainWorld = "0";
3405 $setterForMainWorld = "0";
3406 }
3407
3408 return ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorl d, $data, $accessControl, "static_cast<v8::PropertyAttribute>($propAttribute)", $onProto);
3409 }
3410
3411 sub GenerateAttributeConfiguration
3412 {
3413 my $interface = shift;
3414 my $attribute = shift;
3415 my $delimiter = shift;
3416 my $indent = shift;
3417 my $exposeJSAccessors = shift;
3418
3419 my $code = "";
3420
3421 my ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $ data, $accessControl, $propAttribute, $onProto) = GenerateAttributeConfiguration Parameters($interface, $attribute, $exposeJSAccessors);
3422 if ($exposeJSAccessors) {
3423 $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMain World, $setterForMainWorld, $data, $accessControl, $propAttribute}" . $delimiter . "\n";
3424 } else {
3425 $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMain World, $setterForMainWorld, $data, $accessControl, $propAttribute, $onProto}" . $delimiter . "\n";
3426 }
3427 return $code;
3428 }
3429
3430 sub GenerateStaticAttribute
3431 {
3432 my $interface = shift;
3433 my $attribute = shift;
3434 my $attrExt = $attribute->extendedAttributes;
3435 my $code = "";
3436
3437 my ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $ data, $accessControl, $propAttribute, $onProto) = GenerateAttributeConfiguration Parameters($interface, $attribute);
3438
3439 die "Static attributes do not support optimized getters or setters for the m ain world" if $getterForMainWorld || $setterForMainWorld;
3440
3441 my $conditionalString = GenerateConditionalString($attribute);
3442
3443 $code .= "#if ${conditionalString}\n" if $conditionalString;
3444 $code .= " functionTemplate->SetNativeDataProperty(v8AtomicString(isolate , \"$attrName\"), $getter, $setter, v8::External::New(isolate, $data), $propAttr ibute, v8::Handle<v8::AccessorSignature>(), $accessControl);\n";
3445 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
3446
3447 return $code;
3448 }
3449
3450 sub IsStandardFunction
3451 {
3452 my $interface = shift;
3453 my $function = shift;
3454
3455 my $interfaceName = $interface->name;
3456 my $attrExt = $function->extendedAttributes;
3457 return 0 if $attrExt->{"Unforgeable"};
3458 return 0 if $function->isStatic;
3459 return 0 if $attrExt->{"RuntimeEnabled"};
3460 return 0 if $attrExt->{"PerContextEnabled"};
3461 return 0 if $attrExt->{"DoNotCheckSignature"};
3462 return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttrib utes->{"CheckSecurity"} || $interfaceName eq "Window"));
3463 return 0 if $attrExt->{"NotEnumerable"};
3464 return 0 if $attrExt->{"ReadOnly"};
3465 return 1;
3466 }
3467
3468 sub GenerateNonStandardFunction
3469 {
3470 my $interface = shift;
3471 my $function = shift;
3472 my $code = "";
3473
3474 my $implClassName = GetImplName($interface);
3475 my $attrExt = $function->extendedAttributes;
3476 my $name = $function->name;
3477
3478 my $property_attributes = "v8::DontDelete";
3479 if ($attrExt->{"NotEnumerable"}) {
3480 $property_attributes .= " | v8::DontEnum";
3481 }
3482 if ($attrExt->{"ReadOnly"}) {
3483 $property_attributes .= " | v8::ReadOnly";
3484 }
3485
3486 my $commentInfo = "Function '$name' (Extended Attributes: '" . join(' ', key s(%{$attrExt})) . "')";
3487
3488 my $template = "prototypeTemplate";
3489 if ($attrExt->{"Unforgeable"}) {
3490 $template = "instanceTemplate";
3491 }
3492 if ($function->isStatic) {
3493 $template = "functionTemplate";
3494 }
3495
3496 my $conditional4 = ""; # 4 space indent context
3497 my $conditional8 = ""; # 8 space indent context
3498 if ($attrExt->{"RuntimeEnabled"}) {
3499 # Only call Set()/SetAccessor() if this method should be enabled
3500 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($function);
3501 $conditional4 = "if (${runtimeEnabledFunction}())\n ";
3502 }
3503 if ($attrExt->{"PerContextEnabled"}) {
3504 # Only call Set()/SetAccessor() if this method should be enabled
3505 my $contextEnabledFunction = GetContextEnabledFunctionName($function);
3506 $conditional4 = "if (${contextEnabledFunction}(impl->document()))\n ";
3507 }
3508 $conditional8 = $conditional4 . " " if $conditional4 ne "";
3509
3510 if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCh eckSecurity"}) {
3511 my $setter = $attrExt->{"ReadOnly"} ? "0" : "${implClassName}V8Internal: :${implClassName}OriginSafeMethodSetterCallback";
3512 # Functions that are marked DoNotCheckSecurity are always readable but i f they are changed
3513 # and then accessed on a different domain we do not return the underlyin g value but instead
3514 # return a new copy of the original function. This is achieved by storin g the changed value
3515 # as hidden property.
3516 if ($function->extendedAttributes->{"PerWorldBindings"}) {
3517 $code .= <<END;
3518 if (currentWorldType == MainWorld) {
3519 ${conditional8}$template->SetAccessor(v8AtomicString(isolate, "$name"), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCallbackForMainWorld, $ {setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($p roperty_attributes));
3520 } else {
3521 ${conditional8}$template->SetAccessor(v8AtomicString(isolate, "$name"), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCallback, ${setter}, v8 Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attr ibutes));
3522 }
3523 END
3524 } else {
3525 $code .= " ${conditional4}$template->SetAccessor(v8AtomicString(i solate, \"$name\"), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCal lback, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttri bute>($property_attributes));\n";
3526 }
3527
3528 return $code;
3529 }
3530
3531 my $signature = "defaultSignature";
3532 if ($attrExt->{"DoNotCheckSignature"} || $function->isStatic) {
3533 $signature = "v8::Local<v8::Signature>()";
3534 }
3535
3536 my $conditionalString = GenerateConditionalString($function);
3537 $code .= "#if ${conditionalString}\n" if $conditionalString;
3538
3539 if ($property_attributes eq "v8::DontDelete") {
3540 $property_attributes = "";
3541 } else {
3542 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_a ttributes)";
3543 }
3544
3545 if ($template eq "prototypeTemplate" && $conditional4 eq "" && $signature eq "defaultSignature" && $property_attributes eq "") {
3546 die "This shouldn't happen: Class '$implClassName' $commentInfo\n";
3547 }
3548
3549 my $functionLength = GetFunctionLength($function);
3550
3551 if ($function->extendedAttributes->{"PerWorldBindings"}) {
3552 $code .= " if (currentWorldType == MainWorld) {\n";
3553 $code .= " ${conditional8}$template->Set(v8AtomicString(isolate, \"$name\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${nam e}MethodCallbackForMainWorld, v8Undefined(), ${signature}, $functionLength)$prop erty_attributes);\n";
3554 $code .= " } else {\n";
3555 $code .= " ${conditional8}$template->Set(v8AtomicString(isolate, \"$name\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${nam e}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attribu tes);\n";
3556 $code .= " }\n";
3557 } else {
3558 $code .= " ${conditional4}$template->Set(v8AtomicString(isolate, \"$n ame\"), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}Me thodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes) ;\n";
3559 }
3560 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
3561 return $code;
3562 }
3563
3564 sub GenerateIsNullExpression
3565 {
3566 my $type = shift;
3567 my $variableName = shift;
3568 if (IsUnionType($type)) {
3569 my $types = $type->unionMemberTypes;
3570 my @expression = ();
3571 for my $i (0 .. scalar(@$types)-1) {
3572 my $unionMemberEnabledVariable = $variableName . $i . "Enabled";
3573 push @expression, "!${unionMemberEnabledVariable}";
3574 }
3575 return join " && ", @expression;
3576 }
3577 if (IsRefPtrType($type)) {
3578 return "!${variableName}";
3579 } elsif ($type eq "DOMString") {
3580 return "${variableName}.isNull()";
3581 } elsif ($type eq "Promise") {
3582 return "${variableName}.isNull()";
3583 } else {
3584 return "";
3585 }
3586 }
3587
3588 sub GenerateIfElseStatement
3589 {
3590 my $type = shift;
3591 my $outputVariableName = shift;
3592 my $conditions = shift;
3593 my $statements = shift;
3594
3595 my $code = "";
3596 if (@$conditions == 1) {
3597 $code .= " ${type} ${outputVariableName} = " . $statements->[0] . "\n ";
3598 } else {
3599 $code .= " ${type} ${outputVariableName};\n";
3600 for my $i (0 .. @$conditions - 1) {
3601 my $token = "else if";
3602 $token = "if" if $i == 0;
3603 $token = "else" if $i == @$conditions - 1;
3604 $code .= " ${token}";
3605 $code .= " (" . $conditions->[$i] . ")" if $conditions->[$i];
3606 $code .= "\n";
3607 $code .= " ${outputVariableName} = " . $statements->[$i] . "\ n";
3608 }
3609 }
3610 return $code;
3611 }
3612
3613 sub GenerateImplementationIndexedPropertyAccessors
3614 {
3615 my $interface = shift;
3616 my $interfaceName = $interface->name;
3617 my $implClassName = GetImplName($interface);
3618 my $v8ClassName = GetV8ClassName($interface);
3619
3620 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
3621 if ($indexedGetterFunction) {
3622 # includes for return type even if custom
3623 my $returnType = $indexedGetterFunction->type;
3624 AddIncludesForType($returnType);
3625 my $hasCustomIndexedGetter = $indexedGetterFunction->extendedAttributes- >{"Custom"};
3626 if (!$hasCustomIndexedGetter) {
3627 GenerateImplementationIndexedPropertyGetter($interface, $indexedGett erFunction);
3628 }
3629 GenerateImplementationIndexedPropertyGetterCallback($interface, $hasCust omIndexedGetter);
3630 }
3631
3632 my $indexedSetterFunction = GetIndexedSetterFunction($interface);
3633 if ($indexedSetterFunction) {
3634 AddIncludesForType($indexedSetterFunction->parameters->[1]->type); # in cludes for argument type even if custom
3635 my $hasCustomIndexedSetter = $indexedSetterFunction->extendedAttributes- >{"Custom"};
3636 if (!$hasCustomIndexedSetter) {
3637 GenerateImplementationIndexedPropertySetter($interface, $indexedSett erFunction);
3638 }
3639 GenerateImplementationIndexedPropertySetterCallback($interface, $hasCust omIndexedSetter);
3640 }
3641
3642 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface);
3643 if ($indexedDeleterFunction) {
3644 my $hasCustomIndexedDeleter = $indexedDeleterFunction->extendedAttribute s->{"Custom"};
3645 if (!$hasCustomIndexedDeleter) {
3646 GenerateImplementationIndexedPropertyDeleter($interface, $indexedDel eterFunction);
3647 }
3648 GenerateImplementationIndexedPropertyDeleterCallback($interface, $hasCus tomIndexedDeleter);
3649 }
3650
3651 my $indexedEnumeratorFunction = $indexedGetterFunction;
3652 $indexedEnumeratorFunction = 0 if $indexedGetterFunction && $indexedGetterFu nction->extendedAttributes->{"NotEnumerable"};
3653
3654 my $indexedQueryFunction = 0;
3655 # If there is an enumerator, there MUST be a query method to properly commun icate property attributes.
3656 my $hasQuery = $indexedQueryFunction || $indexedEnumeratorFunction;
3657
3658 my $setOn = "Instance";
3659
3660 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallba cks) and it's used on Window
3661 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
3662 # get implementation straight out of the Window prototype regardless of what prototype is actually set
3663 # on the object.
3664 if ($interfaceName eq "Window") {
3665 $setOn = "Prototype";
3666 }
3667
3668 my $code = "";
3669 if ($indexedGetterFunction || $indexedSetterFunction || $indexedDeleterFunct ion || $indexedEnumeratorFunction || $hasQuery) {
3670 $code .= " functionTemplate->${setOn}Template()->SetIndexedPropertyHa ndler(${implClassName}V8Internal::indexedPropertyGetterCallback";
3671 $code .= $indexedSetterFunction ? ", ${implClassName}V8Internal::indexed PropertySetterCallback" : ", 0";
3672 $code .= ", 0"; # IndexedPropertyQuery -- not being used at the moment.
3673 $code .= $indexedDeleterFunction ? ", ${implClassName}V8Internal::indexe dPropertyDeleterCallback" : ", 0";
3674 $code .= $indexedEnumeratorFunction ? ", indexedPropertyEnumerator<${imp lClassName}>" : ", 0";
3675 $code .= ");\n";
3676 }
3677
3678 return $code;
3679 }
3680
3681 sub GenerateImplementationIndexedPropertyGetter
3682 {
3683 my $interface = shift;
3684 my $indexedGetterFunction = shift;
3685 my $implClassName = GetImplName($interface);
3686 my $v8ClassName = GetV8ClassName($interface);
3687 my $methodName = GetImplName($indexedGetterFunction) || "anonymousIndexedGet ter";
3688 my $interfaceName = $interface->name;
3689
3690 my $returnType = $indexedGetterFunction->type;
3691 my $nativeType = GetNativeType($returnType);
3692 my $nativeValue = "result";
3693 $nativeValue .= ".release()" if (IsRefPtrType($returnType));
3694 my $isNull = GenerateIsNullExpression($returnType, "result");
3695 my $returnJSValueCode = NativeToJSValue($indexedGetterFunction->type, $index edGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.GetIsolate ()", "info", "imp", "", "return");
3696 my $raisesExceptions = $indexedGetterFunction->extendedAttributes->{"RaisesE xception"};
3697 my $methodCallCode = GenerateMethodCall($returnType, "result", "imp->${metho dName}", "index", $raisesExceptions);
3698 my $getterCode = "static void indexedPropertyGetter(uint32_t index, const v8 ::PropertyCallbackInfo<v8::Value>& info)\n";
3699 $getterCode .= "{\n";
3700 $getterCode .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Ho lder());\n";
3701 if ($raisesExceptions) {
3702 $getterCode .= " ExceptionState exceptionState(ExceptionState::Indexe dGetterContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
3703 }
3704 $getterCode .= $methodCallCode . "\n";
3705 if ($raisesExceptions) {
3706 $getterCode .= " if (exceptionState.throwIfNeeded())\n";
3707 $getterCode .= " return;\n";
3708 }
3709 if (IsUnionType($returnType)) {
3710 $getterCode .= "${returnJSValueCode}\n";
3711 $getterCode .= " return;\n";
3712 } else {
3713 $getterCode .= " if (${isNull})\n";
3714 $getterCode .= " return;\n";
3715 $getterCode .= $returnJSValueCode . "\n";
3716 }
3717 $getterCode .= "}\n\n";
3718 $implementation{nameSpaceInternal}->add($getterCode);
3719 }
3720
3721 sub GenerateImplementationIndexedPropertyGetterCallback
3722 {
3723 my $interface = shift;
3724 my $hasCustom = shift;
3725 my $implClassName = GetImplName($interface);
3726 my $v8ClassName = GetV8ClassName($interface);
3727
3728 my $code = "static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3729 $code .= "{\n";
3730 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty \");\n";
3731 if ($hasCustom) {
3732 $code .= " ${v8ClassName}::indexedPropertyGetterCustom(index, info);\ n";
3733 } else {
3734 $code .= " ${implClassName}V8Internal::indexedPropertyGetter(index, i nfo);\n";
3735 }
3736 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3737 $code .= "}\n\n";
3738 $implementation{nameSpaceInternal}->add($code);
3739 }
3740
3741 sub GenerateImplementationIndexedPropertySetterCallback
3742 {
3743 my $interface = shift;
3744 my $hasCustom = shift;
3745 my $implClassName = GetImplName($interface);
3746 my $v8ClassName = GetV8ClassName($interface);
3747
3748 my $code = "static void indexedPropertySetterCallback(uint32_t index, v8::Lo cal<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3749 $code .= "{\n";
3750 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty \");\n";
3751 if ($hasCustom) {
3752 $code .= " ${v8ClassName}::indexedPropertySetterCustom(index, jsValue , info);\n";
3753 } else {
3754 $code .= " ${implClassName}V8Internal::indexedPropertySetter(index, j sValue, info);\n";
3755 }
3756 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3757 $code .= "}\n\n";
3758 $implementation{nameSpaceInternal}->add($code);
3759 }
3760
3761 sub GenerateImplementationIndexedPropertyDeleterCallback
3762 {
3763 my $interface = shift;
3764 my $hasCustom = shift;
3765 my $implClassName = GetImplName($interface);
3766 my $v8ClassName = GetV8ClassName($interface);
3767
3768 my $code = "static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
3769 $code .= "{\n";
3770 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty \");\n";
3771 if ($hasCustom) {
3772 $code .= " ${v8ClassName}::indexedPropertyDeleterCustom(index, info); \n";
3773 } else {
3774 $code .= " ${implClassName}V8Internal::indexedPropertyDeleter(index, info);\n";
3775 }
3776 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3777 $code .= "}\n\n";
3778 $implementation{nameSpaceInternal}->add($code);
3779 }
3780
3781 sub GenerateImplementationIndexedPropertySetter
3782 {
3783 my $interface = shift;
3784 my $indexedSetterFunction = shift;
3785 my $implClassName = GetImplName($interface);
3786 my $v8ClassName = GetV8ClassName($interface);
3787 my $methodName = GetImplName($indexedSetterFunction) || "anonymousIndexedSet ter";
3788 my $interfaceName = $interface->name;
3789
3790 my $type = $indexedSetterFunction->parameters->[1]->type;
3791 my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesE xception"};
3792 my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttribute s->{"TreatNullAs"};
3793 my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttr ibutes->{"TreatUndefinedAs"};
3794
3795 my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8:: Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3796 $code .= "{\n";
3797
3798 my $asSetterValue = 0;
3799 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder() );\n";
3800 $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->t ype, $indexedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "pro pertyValue", " ", "info.GetIsolate()");
3801
3802 my $extraArguments = "";
3803 if ($raisesExceptions || IsIntegerType($type)) {
3804 $code .= " ExceptionState exceptionState(ExceptionState::IndexedSette rContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
3805 if ($raisesExceptions) {
3806 $extraArguments = ", exceptionState";
3807 }
3808 }
3809
3810 if ($indexedSetterFunction->extendedAttributes->{"StrictTypeChecking"} && Is WrapperType($type)) {
3811 $code .= <<END;
3812 if (!isUndefinedOrNull(jsValue) && !V8${type}::hasInstance(jsValue, info.Get Isolate())) {
3813 exceptionState.throwTypeError("The provided value is not of type '$type' .");
3814 exceptionState.throwIfNeeded();
3815 return;
3816 }
3817 END
3818 }
3819
3820 $code .= " bool result = imp->${methodName}(index, propertyValue$extraArg uments);\n";
3821
3822 if ($raisesExceptions) {
3823 $code .= " if (exceptionState.throwIfNeeded())\n";
3824 $code .= " return;\n";
3825 }
3826 $code .= " if (!result)\n";
3827 $code .= " return;\n";
3828 $code .= " v8SetReturnValue(info, jsValue);\n";
3829 $code .= "}\n\n";
3830 $implementation{nameSpaceInternal}->add($code);
3831 }
3832
3833 sub GenerateImplementationNamedPropertyAccessors
3834 {
3835 my $interface = shift;
3836
3837 my $interfaceName = $interface->name;
3838 my $implClassName = GetImplName($interface);
3839 my $v8ClassName = GetV8ClassName($interface);
3840
3841 my $namedGetterFunction = GetNamedGetterFunction($interface);
3842 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction- >extendedAttributes->{"NotEnumerable"};
3843
3844 if ($namedGetterFunction) {
3845 # includes for return type even if custom
3846 my $returnType = $namedGetterFunction->type;
3847 AddIncludesForType($returnType);
3848 my $hasCustomNamedGetter = HasCustomPropertyGetter($namedGetterFunction- >extendedAttributes);
3849 if (!$hasCustomNamedGetter) {
3850 GenerateImplementationNamedPropertyGetter($interface, $namedGetterFu nction);
3851 }
3852 GenerateImplementationNamedPropertyGetterCallback($interface, $hasCustom NamedGetter);
3853 }
3854
3855 my $namedSetterFunction = GetNamedSetterFunction($interface);
3856 if ($namedSetterFunction) {
3857 AddIncludesForType($namedSetterFunction->parameters->[1]->type); # incl udes for argument type even if custom
3858 my $hasCustomNamedSetter = $namedSetterFunction->extendedAttributes->{"C ustom"};
3859 if (!$hasCustomNamedSetter) {
3860 GenerateImplementationNamedPropertySetter($interface, $namedSetterFu nction);
3861 }
3862 GenerateImplementationNamedPropertySetterCallback($interface, $hasCustom NamedSetter);
3863 }
3864
3865 if ($namedEnumeratorFunction) {
3866 my $hasCustomNamedQuery = ExtendedAttributeContains($namedGetterFunction ->extendedAttributes->{"Custom"}, "PropertyQuery");
3867 if (!$hasCustomNamedQuery) {
3868 GenerateImplementationNamedPropertyQuery($interface);
3869 }
3870 GenerateImplementationNamedPropertyQueryCallback($interface, $hasCustomN amedQuery);
3871 }
3872
3873 my $namedDeleterFunction = GetNamedDeleterFunction($interface);
3874 if ($namedDeleterFunction) {
3875 my $hasCustomNamedDeleter = $namedDeleterFunction->extendedAttributes->{ "Custom"};
3876 if (!$hasCustomNamedDeleter) {
3877 GenerateImplementationNamedPropertyDeleter($interface, $namedDeleter Function);
3878 }
3879 GenerateImplementationNamedPropertyDeleterCallback($interface, $hasCusto mNamedDeleter);
3880 }
3881
3882 if ($namedEnumeratorFunction) {
3883 my $hasCustomNamedEnumerator = ExtendedAttributeContains($namedGetterFun ction->extendedAttributes->{"Custom"}, "PropertyEnumerator");
3884 if (!$hasCustomNamedEnumerator) {
3885 GenerateImplementationNamedPropertyEnumerator($interface);
3886 }
3887 GenerateImplementationNamedPropertyEnumeratorCallback($interface, $hasCu stomNamedEnumerator);
3888 }
3889
3890 my $subCode = "";
3891 if ($namedGetterFunction || $namedSetterFunction || $namedDeleterFunction || $namedEnumeratorFunction) {
3892 my $setOn = "Instance";
3893
3894 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCa llbacks) and it's used on Window
3895 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
3896 # get implementation straight out of the Window prototype regardless of what prototype is actually set
3897 # on the object.
3898 if ($interfaceName eq "Window") {
3899 $setOn = "Prototype";
3900 }
3901
3902 $subCode .= " functionTemplate->${setOn}Template()->SetNamedPropertyH andler(";
3903 $subCode .= $namedGetterFunction ? "${implClassName}V8Internal::namedPro pertyGetterCallback, " : "0, ";
3904 $subCode .= $namedSetterFunction ? "${implClassName}V8Internal::namedPro pertySetterCallback, " : "0, ";
3905 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::name dPropertyQueryCallback, " : "0, ";
3906 $subCode .= $namedDeleterFunction ? "${implClassName}V8Internal::namedPr opertyDeleterCallback, " : "0, ";
3907 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::name dPropertyEnumeratorCallback" : "0";
3908 $subCode .= ");\n";
3909 }
3910
3911 return $subCode;
3912 }
3913
3914 sub GenerateImplementationNamedPropertyGetterCallback
3915 {
3916 my $interface = shift;
3917 my $hasCustom = shift;
3918 my $implClassName = GetImplName($interface);
3919 my $v8ClassName = GetV8ClassName($interface);
3920
3921 my $code = "static void namedPropertyGetterCallback(v8::Local<v8::String> na me, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3922 $code .= "{\n";
3923 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3924 if ($hasCustom) {
3925 $code .= " ${v8ClassName}::namedPropertyGetterCustom(name, info);\n";
3926 } else {
3927 $code .= " ${implClassName}V8Internal::namedPropertyGetter(name, info );\n";
3928 }
3929 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3930 $code .= "}\n\n";
3931 $implementation{nameSpaceInternal}->add($code);
3932 }
3933
3934 sub GenerateImplementationNamedPropertySetterCallback
3935 {
3936 my $interface = shift;
3937 my $hasCustom = shift;
3938 my $implClassName = GetImplName($interface);
3939 my $v8ClassName = GetV8ClassName($interface);
3940
3941 my $code = "static void namedPropertySetterCallback(v8::Local<v8::String> na me, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& inf o)\n";
3942 $code .= "{\n";
3943 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3944 if ($hasCustom) {
3945 $code .= " ${v8ClassName}::namedPropertySetterCustom(name, jsValue, i nfo);\n";
3946 } else {
3947 $code .= " ${implClassName}V8Internal::namedPropertySetter(name, jsVa lue, info);\n";
3948 }
3949 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3950 $code .= "}\n\n";
3951 $implementation{nameSpaceInternal}->add($code);
3952 }
3953
3954 sub GenerateImplementationNamedPropertyDeleterCallback
3955 {
3956 my $interface = shift;
3957 my $hasCustom = shift;
3958 my $implClassName = GetImplName($interface);
3959 my $v8ClassName = GetV8ClassName($interface);
3960
3961 my $code = "static void namedPropertyDeleterCallback(v8::Local<v8::String> n ame, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
3962 $code .= "{\n";
3963 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3964 if ($hasCustom) {
3965 $code .= " ${v8ClassName}::namedPropertyDeleterCustom(name, info);\n" ;
3966 } else {
3967 $code .= " ${implClassName}V8Internal::namedPropertyDeleter(name, inf o);\n";
3968 }
3969 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3970 $code .= "}\n\n";
3971 $implementation{nameSpaceInternal}->add($code);
3972 }
3973
3974 sub GenerateImplementationNamedPropertyEnumeratorCallback
3975 {
3976 my $interface = shift;
3977 my $hasCustom = shift;
3978 my $implClassName = GetImplName($interface);
3979 my $v8ClassName = GetV8ClassName($interface);
3980
3981 my $code = "static void namedPropertyEnumeratorCallback(const v8::PropertyCa llbackInfo<v8::Array>& info)\n";
3982 $code .= "{\n";
3983 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3984 if ($hasCustom) {
3985 $code .= " ${v8ClassName}::namedPropertyEnumeratorCustom(info);\n";
3986 } else {
3987 $code .= " ${implClassName}V8Internal::namedPropertyEnumerator(info); \n";
3988 }
3989 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
3990 $code .= "}\n\n";
3991 $implementation{nameSpaceInternal}->add($code);
3992 }
3993
3994 sub GenerateImplementationNamedPropertyQueryCallback
3995 {
3996 my $interface = shift;
3997 my $hasCustom = shift;
3998 my $implClassName = GetImplName($interface);
3999 my $v8ClassName = GetV8ClassName($interface);
4000
4001 my $code = "static void namedPropertyQueryCallback(v8::Local<v8::String> nam e, const v8::PropertyCallbackInfo<v8::Integer>& info)\n";
4002 $code .= "{\n";
4003 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
4004 if ($hasCustom) {
4005 $code .= " ${v8ClassName}::namedPropertyQueryCustom(name, info);\n";
4006 } else {
4007 $code .= " ${implClassName}V8Internal::namedPropertyQuery(name, info) ;\n";
4008 }
4009 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"V8Execution\");\n";
4010 $code .= "}\n\n";
4011 $implementation{nameSpaceInternal}->add($code);
4012 }
4013
4014 sub GenerateMethodCall
4015 {
4016 my $returnType = shift; # string or UnionType
4017 my $returnName = shift;
4018 my $functionExpression = shift;
4019 my $firstArgument = shift;
4020 my $raisesExceptions = shift;
4021
4022 my @arguments = ();
4023 push @arguments, $firstArgument;
4024 if ($raisesExceptions) {
4025 push @arguments, "exceptionState";
4026 }
4027
4028 if (IsUnionType($returnType)) {
4029 my $code = "";
4030 my @extraArguments = ();
4031 for my $i (0..scalar(@{$returnType->unionMemberTypes})-1) {
4032 my $unionMemberType = $returnType->unionMemberTypes->[$i];
4033 my $nativeType = GetNativeType($unionMemberType);
4034 my $unionMemberVariable = $returnName . $i;
4035 my $unionMemberEnabledVariable = $returnName . $i . "Enabled";
4036 $code .= " bool ${unionMemberEnabledVariable} = false;\n";
4037 $code .= " ${nativeType} ${unionMemberVariable};\n";
4038 push @extraArguments, $unionMemberEnabledVariable;
4039 push @extraArguments, $unionMemberVariable;
4040 }
4041 push @arguments, @extraArguments;
4042 $code .= " ${functionExpression}(" . (join ", ", @arguments) . ");";
4043 return $code;
4044 } else {
4045 my $nativeType = GetNativeType($returnType);
4046 return " ${nativeType} result = ${functionExpression}(" . (join ", ", @arguments) . ");"
4047 }
4048 }
4049
4050 sub GenerateImplementationNamedPropertyGetter
4051 {
4052 my $interface = shift;
4053 my $namedGetterFunction = shift;
4054 my $implClassName = GetImplName($interface);
4055 my $v8ClassName = GetV8ClassName($interface);
4056 my $methodName = GetImplName($namedGetterFunction) || "anonymousNamedGetter" ;
4057 my $interfaceName = $interface->name;
4058
4059 my $returnType = $namedGetterFunction->type;
4060 my $isNull = GenerateIsNullExpression($returnType, "result");
4061 my $nativeValue = "result";
4062 $nativeValue .= ".release()" if (IsRefPtrType($returnType));
4063 my $returnJSValueCode = NativeToJSValue($namedGetterFunction->type, $namedGe tterFunction->extendedAttributes, $nativeValue, " ", "", "info.GetIsolate()", "info", "imp", "", "return");
4064 my $raisesExceptions = $namedGetterFunction->extendedAttributes->{"RaisesExc eption"};
4065 my $methodCallCode = GenerateMethodCall($returnType, "result", "imp->${metho dName}", "propertyName", $raisesExceptions);
4066
4067 my $code = "static void namedPropertyGetter(v8::Local<v8::String> name, cons t v8::PropertyCallbackInfo<v8::Value>& info)\n";
4068 $code .= "{\n";
4069 if (!$interface->extendedAttributes->{"OverrideBuiltins"}) {
4070 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n";
4071 $code .= " return;\n";
4072 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n ame).IsEmpty())\n";
4073 $code .= " return;\n";
4074 $code .= "\n";
4075 }
4076 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder() );\n";
4077 $code .= " AtomicString propertyName = toCoreAtomicString(name);\n";
4078 if ($raisesExceptions) {
4079 $code .= " v8::String::Utf8Value namedProperty(name);\n";
4080 $code .= " ExceptionState exceptionState(ExceptionState::GetterContex t, *namedProperty, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
4081 }
4082 $code .= $methodCallCode . "\n";
4083 if ($raisesExceptions) {
4084 $code .= " if (exceptionState.throwIfNeeded())\n";
4085 $code .= " return;\n";
4086 }
4087 $code .= " if (${isNull})\n";
4088 $code .= " return;\n";
4089 $code .= $returnJSValueCode . "\n";
4090 $code .= "}\n\n";
4091 $implementation{nameSpaceInternal}->add($code);
4092 }
4093
4094 sub GenerateImplementationNamedPropertySetter
4095 {
4096 my $interface = shift;
4097 my $namedSetterFunction = shift;
4098 my $implClassName = GetImplName($interface);
4099 my $v8ClassName = GetV8ClassName($interface);
4100 my $methodName = GetImplName($namedSetterFunction) || "anonymousNamedSetter" ;
4101 my $interfaceName = $interface->name;
4102
4103 my $type = $namedSetterFunction->parameters->[1]->type;
4104 my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesExc eption"};
4105 my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes- >{"TreatNullAs"};
4106 my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttrib utes->{"TreatUndefinedAs"};
4107
4108 my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8:: Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
4109 $code .= "{\n";
4110 if (!$interface->extendedAttributes->{"OverrideBuiltins"}) {
4111 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n";
4112 $code .= " return;\n";
4113 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n ame).IsEmpty())\n";
4114 $code .= " return;\n";
4115 $code .= "\n";
4116 }
4117
4118 my $asSetterValue = 0;
4119 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder() );\n";
4120 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->typ e, $namedSetterFunction->extendedAttributes, $asSetterValue, "name", "propertyNa me", " ", "info.GetIsolate()");
4121 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->typ e, $namedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "propert yValue", " ", "info.GetIsolate()");
4122
4123 my $extraArguments = "";
4124 if ($raisesExceptions || IsIntegerType($type)) {
4125 $code .= " v8::String::Utf8Value namedProperty(name);\n";
4126 $code .= " ExceptionState exceptionState(ExceptionState::SetterContex t, *namedProperty, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
4127 if ($raisesExceptions) {
4128 $extraArguments = ", exceptionState";
4129 }
4130 }
4131
4132 $code .= " bool result = imp->$methodName(propertyName, propertyValue$ext raArguments);\n";
4133 if ($raisesExceptions) {
4134 $code .= " if (exceptionState.throwIfNeeded())\n";
4135 $code .= " return;\n";
4136 }
4137 $code .= " if (!result)\n";
4138 $code .= " return;\n";
4139 $code .= " v8SetReturnValue(info, jsValue);\n";
4140 $code .= "}\n\n";
4141 $implementation{nameSpaceInternal}->add($code);
4142 }
4143
4144 sub GenerateImplementationIndexedPropertyDeleter
4145 {
4146 my $interface = shift;
4147 my $indexedDeleterFunction = shift;
4148 my $implClassName = GetImplName($interface);
4149 my $v8ClassName = GetV8ClassName($interface);
4150 my $methodName = GetImplName($indexedDeleterFunction) || "anonymousIndexedDe leter";
4151 my $interfaceName = $interface->name;
4152
4153 my $raisesExceptions = $indexedDeleterFunction->extendedAttributes->{"Raises Exception"};
4154
4155 my $code = "static void indexedPropertyDeleter(uint32_t index, const v8::Pro pertyCallbackInfo<v8::Boolean>& info)\n";
4156 $code .= "{\n";
4157 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder() );\n";
4158 my $extraArguments = "";
4159 if ($raisesExceptions) {
4160 $code .= " ExceptionState exceptionState(ExceptionState::IndexedDelet ionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
4161 $extraArguments = ", exceptionState";
4162 }
4163 $code .= " DeleteResult result = imp->${methodName}(index$extraArguments) ;\n";
4164 if ($raisesExceptions) {
4165 $code .= " if (exceptionState.throwIfNeeded())\n";
4166 $code .= " return;\n";
4167 }
4168 $code .= " if (result != DeleteUnknownProperty)\n";
4169 $code .= " return v8SetReturnValueBool(info, result == DeleteSuccess) ;\n";
4170 $code .= "}\n\n";
4171 $implementation{nameSpaceInternal}->add($code);
4172 }
4173
4174 sub GenerateImplementationNamedPropertyDeleter
4175 {
4176 my $interface = shift;
4177 my $namedDeleterFunction = shift;
4178 my $implClassName = GetImplName($interface);
4179 my $v8ClassName = GetV8ClassName($interface);
4180 my $methodName = GetImplName($namedDeleterFunction) || "anonymousNamedDelete r";
4181 my $interfaceName = $interface->name;
4182
4183 my $raisesExceptions = $namedDeleterFunction->extendedAttributes->{"RaisesEx ception"};
4184
4185 my $code = "static void namedPropertyDeleter(v8::Local<v8::String> name, con st v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
4186 $code .= "{\n";
4187 $code .= " ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder() );\n";
4188 $code .= " AtomicString propertyName = toCoreAtomicString(name);\n";
4189 my $extraArguments = "";
4190 if ($raisesExceptions) {
4191 $code .= " v8::String::Utf8Value namedProperty(name);\n";
4192 $code .= " ExceptionState exceptionState(ExceptionState::DeletionCont ext, *namedProperty, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n" ;
4193 $extraArguments .= ", exceptionState";
4194 }
4195 $code .= " DeleteResult result = imp->${methodName}(propertyName$extraArg uments);\n";
4196 if ($raisesExceptions) {
4197 $code .= " if (exceptionState.throwIfNeeded())\n";
4198 $code .= " return;\n";
4199 }
4200 $code .= " if (result != DeleteUnknownProperty)\n";
4201 $code .= " return v8SetReturnValueBool(info, result == DeleteSuccess) ;\n";
4202 $code .= "}\n\n";
4203 $implementation{nameSpaceInternal}->add($code);
4204 }
4205
4206 sub GenerateImplementationNamedPropertyEnumerator
4207 {
4208 my $interface = shift;
4209 my $implClassName = GetImplName($interface);
4210 my $v8ClassName = GetV8ClassName($interface);
4211 my $interfaceName = $interface->name;
4212
4213 $implementation{nameSpaceInternal}->add(<<END);
4214 static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& i nfo)
4215 {
4216 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
4217 Vector<String> names;
4218 ExceptionState exceptionState(ExceptionState::EnumerationContext, \"${interf aceName}\", info.Holder(), info.GetIsolate());
4219 imp->namedPropertyEnumerator(names, exceptionState);
4220 if (exceptionState.throwIfNeeded())
4221 return;
4222 v8::Handle<v8::Array> v8names = v8::Array::New(info.GetIsolate(), names.size ());
4223 for (size_t i = 0; i < names.size(); ++i)
4224 v8names->Set(v8::Integer::New(info.GetIsolate(), i), v8String(info.GetIs olate(), names[i]));
4225 v8SetReturnValue(info, v8names);
4226 }
4227
4228 END
4229 }
4230
4231 sub GenerateImplementationNamedPropertyQuery
4232 {
4233 my $interface = shift;
4234 my $implClassName = GetImplName($interface);
4235 my $v8ClassName = GetV8ClassName($interface);
4236 my $interfaceName = $interface->name;
4237
4238 $implementation{nameSpaceInternal}->add(<<END);
4239 static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCal lbackInfo<v8::Integer>& info)
4240 {
4241 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
4242 AtomicString propertyName = toCoreAtomicString(name);
4243 v8::String::Utf8Value namedProperty(name);
4244 ExceptionState exceptionState(ExceptionState::GetterContext, *namedProperty, "${interfaceName}", info.Holder(), info.GetIsolate());
4245 bool result = imp->namedPropertyQuery(propertyName, exceptionState);
4246 if (exceptionState.throwIfNeeded())
4247 return;
4248 if (!result)
4249 return;
4250 v8SetReturnValueInt(info, v8::None);
4251 }
4252
4253 END
4254 }
4255
4256 sub GenerateImplementationLegacyCallAsFunction
4257 {
4258 my $interface = shift;
4259 my $code = "";
4260
4261 my $v8ClassName = GetV8ClassName($interface);
4262
4263 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "L egacyCallAsFunction")) {
4264 $code .= " functionTemplate->InstanceTemplate()->SetCallAsFunctionHan dler(${v8ClassName}::legacyCallCustom);\n";
4265 }
4266 return $code;
4267 }
4268
4269 sub GenerateImplementationMarkAsUndetectable
4270 {
4271 my $interface = shift;
4272 my $code = "";
4273
4274 # Needed for legacy support of document.all
4275 if ($interface->name eq "HTMLAllCollection")
4276 {
4277 $code .= " functionTemplate->InstanceTemplate()->MarkAsUndetectable() ;\n";
4278 }
4279 return $code;
4280 }
4281
4282 sub GenerateImplementation
4283 {
4284 my $object = shift;
4285 my $interface = shift;
4286 my $interfaceName = $interface->name;
4287 my $implClassName = GetImplName($interface);
4288 my $v8ClassName = GetV8ClassName($interface);
4289 my $nativeType = GetNativeTypeForConversions($interface);
4290
4291 AddToImplIncludes("RuntimeEnabledFeatures.h");
4292 AddToImplIncludes("bindings/v8/ExceptionState.h");
4293 AddToImplIncludes("core/dom/ContextFeatures.h");
4294 AddToImplIncludes("core/dom/Document.h");
4295 AddToImplIncludes("platform/TraceEvent.h");
4296 AddToImplIncludes("wtf/GetPtr.h");
4297 AddToImplIncludes("wtf/RefPtr.h");
4298
4299 AddIncludesForType($interfaceName);
4300 if ($interface->extendedAttributes->{"CheckSecurity"}) {
4301 AddToImplIncludes("bindings/v8/BindingSecurity.h");
4302 }
4303
4304 my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObje ct") ? "${v8ClassName}::toActiveDOMObject" : "0";
4305 my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8Clas sName}::toEventTarget" : "0";
4306 my $visitDOMWrapper = NeedsVisitDOMWrapper($interface) ? "${v8ClassName}::vi sitDOMWrapper" : "0";
4307 my $derefObject = "${v8ClassName}::derefObject";
4308
4309 # Find the super descriptor.
4310 my $parentClass = "";
4311 my $parentClassTemplate = "";
4312 if ($interface->parent) {
4313 my $parent = $interface->parent;
4314 $parentClass = "V8" . $parent;
4315 $parentClassTemplate = $parentClass . "::domTemplate(isolate, currentWor ldType)";
4316 }
4317
4318 my $parentClassInfo = $parentClass ? "&${parentClass}::wrapperTypeInfo" : "0 ";
4319 my $WrapperTypePrototype = $interface->isException ? "WrapperTypeExceptionPr ototype" : "WrapperTypeObjectPrototype";
4320
4321 if (!IsSVGTypeNeedingTearOff($interfaceName)) {
4322 my $code = <<END;
4323 static void initializeScriptWrappableForInterface(${implClassName}* object)
4324 {
4325 if (ScriptWrappable::wrapperCanBeStoredInObject(object))
4326 ScriptWrappable::setTypeInfoInObject(object, &${v8ClassName}::wrapperTyp eInfo);
4327 else
4328 ASSERT_NOT_REACHED();
4329 }
4330
4331 } // namespace WebCore
4332
4333 // In ScriptWrappable::init, the use of a local function declaration has an issu e on Windows:
4334 // the local declaration does not pick up the surrounding namespace. Therefore, we provide this function
4335 // in the global namespace.
4336 // (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/fe edback/details/664619/the-namespace-of-local-function-declarations-in-c)
4337 END
4338
4339 if (GetNamespaceForInterface($interface) eq "WebCore") {
4340 $code .= "void webCoreInitializeScriptWrappableForInterface(WebCore::${i mplClassName}* object)\n";
4341 } else {
4342 $code .= "void webCoreInitializeScriptWrappableForInterface(${implClassN ame}* object)\n";
4343 }
4344
4345 $code .= <<END;
4346 {
4347 WebCore::initializeScriptWrappableForInterface(object);
4348 }
4349
4350 namespace WebCore {
4351 END
4352 $implementation{nameSpaceWebCore}->addHeader($code);
4353 }
4354
4355 my $code = "const WrapperTypeInfo ${v8ClassName}::wrapperTypeInfo = { gin::k EmbedderBlink, ${v8ClassName}::domTemplate, $derefObject, $toActiveDOMObject, $t oEventTarget, ";
4356 $code .= "$visitDOMWrapper, ${v8ClassName}::installPerContextEnabledMethods, $parentClassInfo, $WrapperTypePrototype, ";
4357 $code .= IsWillBeGarbageCollectedType($interfaceName) ? "true" : "false";
4358 $code .= " };\n";
4359 $implementation{nameSpaceWebCore}->addHeader($code);
4360
4361 $implementation{nameSpaceInternal}->add("template <typename T> void V8_USE(T ) { }\n\n");
4362
4363 my $hasConstructors = 0;
4364 my $hasReplaceable = 0;
4365
4366 # Generate property accessors for attributes.
4367 for (my $index = 0; $index < @{$interface->attributes}; $index++) {
4368 my $attribute = @{$interface->attributes}[$index];
4369 my $attrType = $attribute->type;
4370 my $attrExt = $attribute->extendedAttributes;
4371
4372 # Generate special code for the constructor attributes.
4373 if ($attrType =~ /Constructor$/) {
4374 if (!HasCustomGetter($attrExt)) {
4375 $hasConstructors = 1;
4376 }
4377 next;
4378 }
4379
4380 AddIncludesForType($attrType);
4381
4382 if ($attrType eq "EventHandler" && $interfaceName eq "Window") {
4383 $attrExt->{"OnPrototype"} = 1;
4384 }
4385
4386 if ($attrType eq "SerializedScriptValue") {
4387 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
4388 }
4389
4390 my $isReplaceable = 0;
4391 if (!HasCustomSetter($attribute) && !$attrExt->{"PutForwards"} && $attrE xt->{"Replaceable"}) {
4392 $isReplaceable = 1;
4393 $hasReplaceable = 1;
4394 }
4395
4396 my $exposeJSAccessors = $attrExt->{"ExposeJSAccessors"};
4397 my @worldSuffixes = ("");
4398 if ($attrExt->{"PerWorldBindings"}) {
4399 push(@worldSuffixes, "ForMainWorld");
4400 }
4401 foreach my $worldSuffix (@worldSuffixes) {
4402 GenerateNormalAttributeGetter($attribute, $interface, $worldSuffix, $exposeJSAccessors);
4403 GenerateNormalAttributeGetterCallback($attribute, $interface, $world Suffix, $exposeJSAccessors);
4404 if (!$isReplaceable && !IsReadonly($attribute)) {
4405 GenerateNormalAttributeSetter($attribute, $interface, $worldSuff ix, $exposeJSAccessors);
4406 GenerateNormalAttributeSetterCallback($attribute, $interface, $w orldSuffix, $exposeJSAccessors);
4407 }
4408 }
4409 }
4410
4411 if ($hasConstructors) {
4412 GenerateConstructorGetter($interface);
4413 }
4414
4415 if ($hasConstructors || $hasReplaceable) {
4416 GenerateReplaceableAttributeSetter($interface);
4417 GenerateReplaceableAttributeSetterCallback($interface);
4418 }
4419
4420 if (NeedsVisitDOMWrapper($interface)) {
4421 GenerateVisitDOMWrapper($interface);
4422 }
4423
4424 if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne "Window") {
4425 GenerateSecurityCheckFunctions($interface);
4426 }
4427
4428 my @perContextEnabledFunctions;
4429 my @normalFunctions;
4430 my $needsDomainSafeFunctionSetter = 0;
4431 # Generate methods for functions.
4432 foreach my $function (@{$interface->functions}) {
4433 next if $function->name eq ""; # Skip anonymous special operations
4434 my @worldSuffixes = ("");
4435 if ($function->extendedAttributes->{"PerWorldBindings"}) {
4436 push(@worldSuffixes, "ForMainWorld");
4437 }
4438 foreach my $worldSuffix (@worldSuffixes) {
4439 GenerateFunction($function, $interface, $worldSuffix);
4440 if ($function->{overloadIndex} == @{$function->{overloads}}) {
4441 if ($function->{overloadIndex} > 1) {
4442 GenerateOverloadedFunction($function, $interface, $worldSuff ix);
4443 }
4444 GenerateFunctionCallback($function, $interface, $worldSuffix);
4445 }
4446
4447 # If the function does not need domain security check, we need to
4448 # generate an access getter that returns different function objects
4449 # for different calling context.
4450 if ($interface->extendedAttributes->{"CheckSecurity"} && $function-> extendedAttributes->{"DoNotCheckSecurity"} && (!HasCustomMethod($function->exten dedAttributes) || $function->{overloadIndex} == 1)) {
4451 GenerateDomainSafeFunctionGetter($function, $interface, $worldSu ffix);
4452 if (!$function->extendedAttributes->{"ReadOnly"}) {
4453 $needsDomainSafeFunctionSetter = 1;
4454 }
4455 }
4456 }
4457
4458 # Separate out functions that are enabled per context so we can process them specially.
4459 if ($function->extendedAttributes->{"PerContextEnabled"}) {
4460 push(@perContextEnabledFunctions, $function);
4461 } else {
4462 push(@normalFunctions, $function);
4463 }
4464 }
4465
4466 if ($needsDomainSafeFunctionSetter) {
4467 GenerateDomainSafeFunctionSetter($interface);
4468 }
4469
4470 # Attributes
4471 my $attributes = $interface->attributes;
4472
4473 # For the Window interface we partition the attributes into the
4474 # ones that disallows shadowing and the rest.
4475 my @disallowsShadowing;
4476 # Also separate out attributes that are enabled at runtime so we can process them specially.
4477 my @runtimeEnabledAttributes;
4478 my @perContextEnabledAttributes;
4479 my @normalAttributes;
4480 my @normalAccessors;
4481 my @staticAttributes;
4482 foreach my $attribute (@$attributes) {
4483
4484 if ($attribute->isStatic) {
4485 push(@staticAttributes, $attribute);
4486 } elsif ($interfaceName eq "Window" && $attribute->extendedAttributes->{ "Unforgeable"}) {
4487 push(@disallowsShadowing, $attribute);
4488 } elsif ($attribute->extendedAttributes->{"PerContextEnabled"}) {
4489 push(@perContextEnabledAttributes, $attribute);
4490 } elsif ($attribute->extendedAttributes->{"RuntimeEnabled"}) {
4491 push(@runtimeEnabledAttributes, $attribute);
4492 } elsif ($attribute->extendedAttributes->{"ExposeJSAccessors"}) {
4493 push(@normalAccessors, $attribute);
4494 } else {
4495 push(@normalAttributes, $attribute);
4496 }
4497 }
4498 AddToImplIncludes("bindings/v8/V8DOMConfiguration.h");
4499 # Put the attributes that disallow shadowing on the shadow object.
4500 if (@disallowsShadowing) {
4501 my $code = "";
4502 $code .= "static const V8DOMConfiguration::AttributeConfiguration shadow Attributes[] = {\n";
4503 $code .= GenerateAttributeConfigurationArray($interface, \@disallowsShad owing);
4504 $code .= "};\n\n";
4505 $implementation{nameSpaceWebCore}->add($code);
4506 }
4507
4508 my $hasAttributes = 0;
4509 if (@normalAttributes) {
4510 $hasAttributes = 1;
4511 my $code = "";
4512 $code .= "static const V8DOMConfiguration::AttributeConfiguration ${v8Cl assName}Attributes[] = {\n";
4513 $code .= GenerateAttributeConfigurationArray($interface, \@normalAttribu tes);
4514 $code .= "};\n\n";
4515 $implementation{nameSpaceWebCore}->add($code);
4516 }
4517
4518 my $hasAccessors = 0;
4519 if (@normalAccessors) {
4520 $hasAccessors = 1;
4521 my $code = "";
4522 $code .= "static const V8DOMConfiguration::AccessorConfiguration ${v8Cla ssName}Accessors[] = {\n";
4523 $code .= GenerateAttributeConfigurationArray($interface, \@normalAccesso rs, "accessor");
4524 $code .= "};\n\n";
4525 $implementation{nameSpaceWebCore}->add($code);
4526 }
4527
4528 # Setup table of standard callback functions
4529 my $hasFunctions = 0;
4530 $code = "";
4531 foreach my $function (@normalFunctions) {
4532 # Only one table entry is needed for overloaded functions:
4533 next if $function->{overloadIndex} > 1;
4534 # Don't put any nonstandard functions into this table:
4535 next if !IsStandardFunction($interface, $function);
4536 next if $function->name eq "";
4537 if (!$hasFunctions) {
4538 $hasFunctions = 1;
4539 $code .= "static const V8DOMConfiguration::MethodConfiguration ${v8C lassName}Methods[] = {\n";
4540 }
4541 my $name = $function->name;
4542 my $methodForMainWorld = "0";
4543 if ($function->extendedAttributes->{"PerWorldBindings"}) {
4544 $methodForMainWorld = "${implClassName}V8Internal::${name}MethodCall backForMainWorld";
4545 }
4546 my $functionLength = GetFunctionLength($function);
4547 my $conditionalString = GenerateConditionalString($function);
4548 $code .= "#if ${conditionalString}\n" if $conditionalString;
4549 $code .= <<END;
4550 {"$name", ${implClassName}V8Internal::${name}MethodCallback, ${methodForMain World}, ${functionLength}},
4551 END
4552 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4553 }
4554 $code .= "};\n\n" if $hasFunctions;
4555 $implementation{nameSpaceWebCore}->add($code);
4556
4557 my $hasConstants = 0;
4558 if (@{$interface->constants}) {
4559 $hasConstants = 1;
4560 }
4561
4562 if (!HasCustomConstructor($interface)) {
4563 if ($interface->extendedAttributes->{"NamedConstructor"}) {
4564 GenerateNamedConstructor(@{$interface->constructors}[0], $interface) ;
4565 } elsif ($interface->extendedAttributes->{"Constructor"}) {
4566 GenerateConstructor($interface);
4567 } elsif ($interface->extendedAttributes->{"EventConstructor"}) {
4568 GenerateEventConstructor($interface);
4569 }
4570 }
4571 if (IsConstructable($interface)) {
4572 GenerateConstructorCallback($interface);
4573 }
4574
4575 my $accessCheck = "";
4576 if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne " Window") {
4577 $accessCheck = "instanceTemplate->SetAccessCheckCallbacks(${implClassNam e}V8Internal::namedSecurityCheck, ${implClassName}V8Internal::indexedSecurityChe ck, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&${v8ClassName}::wra pperTypeInfo)));";
4578 }
4579
4580 # For the Window interface, generate the shadow object template
4581 # configuration method.
4582 if ($interfaceName eq "Window") {
4583 $implementation{nameSpaceWebCore}->add(<<END);
4584 static void configureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ, v8::Isolate* isolate, WrapperWorldType currentWorldType)
4585 {
4586 V8DOMConfiguration::installAttributes(templ, v8::Handle<v8::ObjectTemplate>( ), shadowAttributes, WTF_ARRAY_LENGTH(shadowAttributes), isolate, currentWorldTy pe);
4587
4588 // Install a security handler with V8.
4589 templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window: :indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeIn fo*>(&V8Window::wrapperTypeInfo)));
4590 templ->SetInternalFieldCount(V8Window::internalFieldCount);
4591 }
4592
4593 END
4594 }
4595
4596 if (!$parentClassTemplate) {
4597 $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()";
4598 }
4599
4600 # Generate the template configuration method
4601 $code = <<END;
4602 static void configure${v8ClassName}Template(v8::Handle<v8::FunctionTemplate> fun ctionTemplate, v8::Isolate* isolate, WrapperWorldType currentWorldType)
4603 {
4604 functionTemplate->ReadOnlyPrototype();
4605
4606 v8::Local<v8::Signature> defaultSignature;
4607 END
4608
4609 # Define constants, attributes, accessors and operations.
4610 my $runtimeEnabledIndent = "";
4611 if ($interface->extendedAttributes->{"RuntimeEnabled"}) {
4612 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($interface);
4613 $runtimeEnabledIndent = " ";
4614 $code .= <<END;
4615 if (!${runtimeEnabledFunction}())
4616 defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionT emplate, \"\", $parentClassTemplate, ${v8ClassName}::internalFieldCount, 0, 0, 0 , 0, 0, 0, isolate, currentWorldType);
4617 else
4618 END
4619 }
4620 $code .= $runtimeEnabledIndent . " defaultSignature = V8DOMConfiguration: :installDOMClassTemplate(functionTemplate, \"${interfaceName}\", $parentClassTem plate, ${v8ClassName}::internalFieldCount,\n";
4621 $code .= $runtimeEnabledIndent . " " . ($hasAttributes ? "${v8ClassNa me}Attributes, WTF_ARRAY_LENGTH(${v8ClassName}Attributes),\n" : "0, 0,\n");
4622 $code .= $runtimeEnabledIndent . " " . ($hasAccessors ? "${v8ClassNam e}Accessors, WTF_ARRAY_LENGTH(${v8ClassName}Accessors),\n" : "0, 0,\n");
4623 $code .= $runtimeEnabledIndent . " " . ($hasFunctions ? "${v8ClassNam e}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods),\n" : "0, 0,\n");
4624 $code .= $runtimeEnabledIndent . " isolate, currentWorldType);\n";
4625
4626 if (IsConstructable($interface)) {
4627 $code .= " functionTemplate->SetCallHandler(${v8ClassName}::construct orCallback);\n";
4628 my $interfaceLength = GetInterfaceLength($interface);
4629 $code .= " functionTemplate->SetLength(${interfaceLength});\n";
4630 }
4631
4632 $code .= <<END;
4633 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED instanceTemplate = functionTempla te->InstanceTemplate();
4634 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED prototypeTemplate = functionTempl ate->PrototypeTemplate();
4635 END
4636
4637 if ($accessCheck) {
4638 $code .= " $accessCheck\n";
4639 }
4640
4641 # Define runtime enabled attributes.
4642 foreach my $runtimeEnabledAttribute (@runtimeEnabledAttributes) {
4643 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($runtimeEnabl edAttribute);
4644 my $conditionalString = GenerateConditionalString($runtimeEnabledAttribu te);
4645 $code .= "#if ${conditionalString}\n" if $conditionalString;
4646 $code .= " if (${runtimeEnabledFunction}()) {\n";
4647 $code .= " static const V8DOMConfiguration::AttributeConfiguratio n attributeConfiguration =\\\n";
4648 $code .= GenerateAttributeConfiguration($interface, $runtimeEnabledAttri bute, ";", " ");
4649 $code .= <<END;
4650 V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate , attributeConfiguration, isolate, currentWorldType);
4651 }
4652 END
4653 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4654 }
4655
4656 my @runtimeEnabledConstants;
4657 if ($hasConstants) {
4658 # Define constants.
4659 $code .= " static const V8DOMConfiguration::ConstantConfiguration ${v 8ClassName}Constants[] = {\n";
4660 foreach my $constant (@{$interface->constants}) {
4661 my $name = $constant->name;
4662 my $value = $constant->value;
4663 my $attrExt = $constant->extendedAttributes;
4664 my $implementedBy = $attrExt->{"ImplementedBy"};
4665 if ($implementedBy) {
4666 my $implementedByImplName = GetImplNameFromImplementedBy($implem entedBy);
4667 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $imple mentedByImplName));
4668 }
4669 if ($attrExt->{"RuntimeEnabled"}) {
4670 push(@runtimeEnabledConstants, $constant);
4671 } else {
4672 $code .= <<END;
4673 {"${name}", $value},
4674 END
4675 }
4676 }
4677 $code .= " };\n";
4678 $code .= <<END;
4679 V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate, ${ v8ClassName}Constants, WTF_ARRAY_LENGTH(${v8ClassName}Constants), isolate);
4680 END
4681 # Define runtime enabled constants.
4682 foreach my $runtimeEnabledConstant (@runtimeEnabledConstants) {
4683 my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($runtimeE nabledConstant);
4684 my $name = $runtimeEnabledConstant->name;
4685 my $value = $runtimeEnabledConstant->value;
4686 $code .= " if (${runtimeEnabledFunction}()) {\n";
4687 $code .= <<END;
4688 static const V8DOMConfiguration::ConstantConfiguration constantConfigura tion = {"${name}", static_cast<signed int>(${value})};
4689 V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate , &constantConfiguration, 1, isolate);
4690 END
4691 $code .= " }\n";
4692 }
4693 $code .= join "", GenerateCompileTimeCheckForEnumsIfNeeded($interface);
4694 }
4695
4696 $code .= GenerateImplementationIndexedPropertyAccessors($interface);
4697 $code .= GenerateImplementationNamedPropertyAccessors($interface);
4698 $code .= GenerateImplementationLegacyCallAsFunction($interface);
4699 $code .= GenerateImplementationMarkAsUndetectable($interface);
4700
4701 # Define operations.
4702 my $total_functions = 0;
4703 foreach my $function (@normalFunctions) {
4704 # Only one accessor is needed for overloaded operations.
4705 next if $function->{overloadIndex} > 1;
4706 next if $function->name eq "";
4707
4708 $total_functions++;
4709 next if IsStandardFunction($interface, $function);
4710 $code .= GenerateNonStandardFunction($interface, $function);
4711 }
4712
4713 # Define static attributes.
4714 foreach my $attribute (@staticAttributes) {
4715 $code .= GenerateStaticAttribute($interface, $attribute);
4716 }
4717
4718 # Special cases
4719 if ($interfaceName eq "Window") {
4720 $code .= <<END;
4721
4722 prototypeTemplate->SetInternalFieldCount(V8Window::internalFieldCount);
4723 functionTemplate->SetHiddenPrototype(true);
4724 instanceTemplate->SetInternalFieldCount(V8Window::internalFieldCount);
4725 // Set access check callbacks, but turned off initially.
4726 // When a context is detached from a frame, turn on the access check.
4727 // Turning on checks also invalidates inline caches of the object.
4728 instanceTemplate->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom , V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<Wr apperTypeInfo*>(&V8Window::wrapperTypeInfo)), false);
4729 END
4730 }
4731 if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGl obalScope" or $interfaceName eq "SharedWorkerGlobalScope" or $interfaceName eq " ServiceWorkerGlobalScope") {
4732 $code .= <<END;
4733 functionTemplate->SetHiddenPrototype(true);
4734 END
4735 }
4736
4737 $code .= <<END;
4738
4739 // Custom toString template
4740 functionTemplate->Set(v8AtomicString(isolate, "toString"), V8PerIsolateData: :current()->toStringTemplate());
4741 }
4742
4743 END
4744 $implementation{nameSpaceWebCore}->add($code);
4745
4746 AddToImplIncludes("bindings/v8/V8ObjectConstructor.h");
4747 $implementation{nameSpaceWebCore}->add(<<END);
4748 v8::Handle<v8::FunctionTemplate> ${v8ClassName}::domTemplate(v8::Isolate* isolat e, WrapperWorldType currentWorldType)
4749 {
4750 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
4751 V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWo rldType).find(&wrapperTypeInfo);
4752 if (result != data->templateMap(currentWorldType).end())
4753 return result->value.newLocal(isolate);
4754
4755 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4756 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate, V 8ObjectConstructor::isValidConstructorMode);
4757 configure${v8ClassName}Template(templ, isolate, currentWorldType);
4758 data->templateMap(currentWorldType).add(&wrapperTypeInfo, UnsafePersistent<v 8::FunctionTemplate>(isolate, templ));
4759 return templ;
4760 }
4761
4762 bool ${v8ClassName}::hasInstance(v8::Handle<v8::Value> jsValue, v8::Isolate* iso late)
4763 {
4764 return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e);
4765 }
4766
4767 v8::Handle<v8::Object> ${v8ClassName}::findInstanceInPrototypeChain(v8::Handle<v 8::Value> jsValue, v8::Isolate* isolate)
4768 {
4769 return V8PerIsolateData::from(isolate)->findInstanceInPrototypeChain(&wrappe rTypeInfo, jsValue);
4770 }
4771
4772 ${nativeType}* ${v8ClassName}::toNativeWithTypeCheck(v8::Isolate* isolate, v8::H andle<v8::Value> value)
4773 {
4774 return hasInstance(value, isolate) ? fromInternalPointer(v8::Handle<v8::Obje ct>::Cast(value)->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)) : 0;
4775 }
4776
4777 END
4778
4779 if (@perContextEnabledAttributes) {
4780 my $code = "";
4781 $code .= <<END;
4782 void ${v8ClassName}::installPerContextEnabledProperties(v8::Handle<v8::Object> i nstanceTemplate, ${nativeType}* impl, v8::Isolate* isolate)
4783 {
4784 v8::Local<v8::Object> prototypeTemplate = v8::Local<v8::Object>::Cast(instan ceTemplate->GetPrototype());
4785 END
4786
4787 # Define per-context enabled attributes.
4788 foreach my $perContextEnabledAttribute (@perContextEnabledAttributes) {
4789 my $contextEnabledFunction = GetContextEnabledFunctionName($perConte xtEnabledAttribute);
4790 $code .= " if (${contextEnabledFunction}(impl->document())) {\n";
4791
4792 $code .= " static const V8DOMConfiguration::AttributeConfigur ation attributeConfiguration =\\\n";
4793 $code .= GenerateAttributeConfiguration($interface, $perContextEnabl edAttribute, ";", " ");
4794 $code .= <<END;
4795 V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate , attributeConfiguration, isolate);
4796 END
4797 $code .= " }\n";
4798 }
4799 $code .= <<END;
4800 }
4801
4802 END
4803 $implementation{nameSpaceWebCore}->add($code);
4804 }
4805
4806 if (@perContextEnabledFunctions) {
4807 my $code = "";
4808 $code .= <<END;
4809 void ${v8ClassName}::installPerContextEnabledMethods(v8::Handle<v8::Object> prot otypeTemplate, v8::Isolate* isolate)
4810 {
4811 END
4812 # Define per-context enabled operations.
4813 $code .= <<END;
4814 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(isolate, domT emplate(isolate, worldType(isolate)));
4815
4816 ExecutionContext* context = toExecutionContext(prototypeTemplate->CreationCo ntext());
4817 END
4818
4819 foreach my $perContextEnabledFunction (@perContextEnabledFunctions) {
4820 my $contextEnabledFunction = GetContextEnabledFunctionName($perConte xtEnabledFunction);
4821 my $functionLength = GetFunctionLength($perContextEnabledFunction);
4822 my $conditionalString = GenerateConditionalString($perContextEnabled Function);
4823 $code .= "\n#if ${conditionalString}\n" if $conditionalString;
4824 $code .= " if (context && context->isDocument() && ${contextEnabl edFunction}(toDocument(context)))\n";
4825 my $name = $perContextEnabledFunction->name;
4826 $code .= <<END;
4827 prototypeTemplate->Set(v8AtomicString(isolate, "$name"), v8::FunctionTem plate::New(isolate, ${implClassName}V8Internal::${name}MethodCallback, v8Undefin ed(), defaultSignature, $functionLength)->GetFunction());
4828 END
4829 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4830 }
4831
4832 $code .= <<END;
4833 }
4834
4835 END
4836 $implementation{nameSpaceWebCore}->add($code);
4837 }
4838
4839 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
4840 $implementation{nameSpaceWebCore}->add(<<END);
4841 ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> wrappe r)
4842 {
4843 return toNative(wrapper);
4844 }
4845
4846 END
4847 }
4848
4849 if (InheritsInterface($interface, "EventTarget")) {
4850 $implementation{nameSpaceWebCore}->add(<<END);
4851 EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object)
4852 {
4853 return toNative(object);
4854 }
4855
4856 END
4857 }
4858
4859 if ($interfaceName eq "Window") {
4860 $implementation{nameSpaceWebCore}->add(<<END);
4861 v8::Handle<v8::ObjectTemplate> V8Window::getShadowObjectTemplate(v8::Isolate* is olate, WrapperWorldType currentWorldType)
4862 {
4863 if (currentWorldType == MainWorld) {
4864 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowOb jectCacheForMainWorld, ());
4865 if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) {
4866 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4867 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isola te);
4868 configureShadowObjectTemplate(templ, isolate, currentWorldType);
4869 V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ);
4870 return templ;
4871 }
4872 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectC acheForMainWorld);
4873 } else {
4874 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowOb jectCacheForNonMainWorld, ());
4875 if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) {
4876 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4877 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isola te);
4878 configureShadowObjectTemplate(templ, isolate, currentWorldType);
4879 V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ);
4880 return templ;
4881 }
4882 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectC acheForNonMainWorld);
4883 }
4884 }
4885
4886 END
4887 }
4888
4889 GenerateSpecialWrap($interface, $v8ClassName);
4890 GenerateToV8Converters($interface, $v8ClassName);
4891
4892 $implementation{nameSpaceWebCore}->add("void ${v8ClassName}::derefObject(voi d* object)\n");
4893 $implementation{nameSpaceWebCore}->add("{\n");
4894 if (IsWillBeGarbageCollectedType($interface->name)) {
4895 $implementation{nameSpaceWebCore}->add("#if !ENABLE(OILPAN)\n");
4896 }
4897 $implementation{nameSpaceWebCore}->add(" fromInternalPointer(object)->der ef();\n");
4898 if (IsWillBeGarbageCollectedType($interface->name)) {
4899 $implementation{nameSpaceWebCore}->add("#endif // !ENABLE(OILPAN)\n");
4900 }
4901 $implementation{nameSpaceWebCore}->add("}\n\n");
4902
4903 $implementation{nameSpaceWebCore}->add(<<END);
4904 template<>
4905 v8::Handle<v8::Value> toV8NoInline(${nativeType}* impl, v8::Handle<v8::Object> c reationContext, v8::Isolate* isolate)
4906 {
4907 return toV8(impl, creationContext, isolate);
4908 }
4909
4910 END
4911 }
4912
4913 sub GenerateHeaderContentHeader
4914 {
4915 my $interface = shift;
4916 my $v8ClassName = GetV8ClassName($interface);
4917 my $conditionalString = GenerateConditionalString($interface);
4918
4919 my @headerContentHeader = split("\r", $licenseHeader);
4920
4921 push(@headerContentHeader, "#ifndef ${v8ClassName}" . "_h\n");
4922 push(@headerContentHeader, "#define ${v8ClassName}" . "_h\n\n");
4923 push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalStri ng;
4924 return join "", @headerContentHeader;
4925 }
4926
4927 sub GenerateCallbackHeader
4928 {
4929 my $object = shift;
4930 my $interface = shift;
4931
4932 my $interfaceName = $interface->name;
4933 my $implClassName = GetImplName($interface);
4934 my $v8ClassName = GetV8ClassName($interface);
4935
4936 my @includes = ();
4937 push(@includes, "bindings/v8/ActiveDOMCallback.h");
4938 push(@includes, "bindings/v8/DOMWrapperWorld.h");
4939 push(@includes, "bindings/v8/ScopedPersistent.h");
4940 push(@includes, HeaderFilesForInterface($interfaceName, $implClassName));
4941 for my $include (sort @includes) {
4942 $header{includes}->add("#include \"$include\"\n");
4943 }
4944 $header{nameSpaceWebCore}->addHeader("\nclass ExecutionContext;\n");
4945 $header{class}->addHeader("class $v8ClassName FINAL : public $implClassName, public ActiveDOMCallback {");
4946 $header{class}->addFooter("};\n");
4947
4948 $header{classPublic}->add(<<END);
4949 static PassOwnPtr<${v8ClassName}> create(v8::Handle<v8::Function> callback, ExecutionContext* context)
4950 {
4951 ASSERT(context);
4952 return adoptPtr(new ${v8ClassName}(callback, context));
4953 }
4954
4955 virtual ~${v8ClassName}();
4956
4957 END
4958
4959 # Functions
4960 my $numFunctions = @{$interface->functions};
4961 if ($numFunctions > 0) {
4962 foreach my $function (@{$interface->functions}) {
4963 my $code = " virtual " . GetNativeTypeForCallbacks($function->typ e) . " " . $function->name . "(";
4964
4965 my @args = ();
4966 if (ExtendedAttributeContains($function->extendedAttributes->{"CallW ith"}, "ThisValue")) {
4967 push(@args, GetNativeType("any") . " thisValue");
4968 }
4969 my @params = @{$function->parameters};
4970 foreach my $param (@params) {
4971 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $par am->name);
4972 }
4973 $code .= join(", ", @args);
4974 $code .= ") OVERRIDE;\n";
4975 $header{classPublic}->add($code);
4976 }
4977 }
4978
4979 $header{classPrivate}->add(<<END);
4980 ${v8ClassName}(v8::Handle<v8::Function>, ExecutionContext*);
4981
4982 v8::Isolate* m_isolate;
4983 ScopedPersistent<v8::Function> m_callback;
4984 RefPtr<DOMWrapperWorld> m_world;
4985 END
4986 }
4987
4988 sub GenerateCallbackImplementation
4989 {
4990 my $object = shift;
4991 my $interface = shift;
4992 my $v8ClassName = GetV8ClassName($interface);
4993
4994 AddToImplIncludes("core/dom/ExecutionContext.h");
4995 AddToImplIncludes("bindings/v8/V8Binding.h");
4996 AddToImplIncludes("bindings/v8/V8Callback.h");
4997 AddToImplIncludes("wtf/Assertions.h");
4998 AddToImplIncludes("wtf/GetPtr.h");
4999 AddToImplIncludes("wtf/RefPtr.h");
5000
5001 $implementation{nameSpaceWebCore}->add(<<END);
5002 ${v8ClassName}::${v8ClassName}(v8::Handle<v8::Function> callback, ExecutionConte xt* context)
5003 : ActiveDOMCallback(context)
5004 , m_isolate(toIsolate(context))
5005 , m_callback(m_isolate, callback)
5006 , m_world(DOMWrapperWorld::current(m_isolate))
5007 {
5008 }
5009
5010 END
5011
5012 $implementation{nameSpaceWebCore}->add(<<END);
5013 ${v8ClassName}::~${v8ClassName}()
5014 {
5015 }
5016
5017 END
5018
5019 # Functions
5020 my $numFunctions = @{$interface->functions};
5021 if ($numFunctions > 0) {
5022 foreach my $function (@{$interface->functions}) {
5023 my $code = "";
5024 my @params = @{$function->parameters};
5025
5026 # Add includes for types even if custom
5027 AddIncludesForType($function->type);
5028 foreach my $param (@params) {
5029 AddIncludesForType($param->type);
5030 }
5031 next if $function->extendedAttributes->{"Custom"};
5032
5033 die "We only support callbacks that return boolean or void values.\n " unless ($function->type eq "boolean" || $function->type eq "void");
5034 my $defaultReturn = $function->type eq "boolean" ? " true" : "";
5035 $code .= GetNativeTypeForCallbacks($function->type) . " ${v8ClassNam e}::" . $function->name . "(";
5036 my $callWithThisValue = ExtendedAttributeContains($function->extende dAttributes->{"CallWith"}, "ThisValue");
5037
5038 my @args = ();
5039 if ($callWithThisValue) {
5040 push(@args, GetNativeTypeForCallbacks("any") . " thisValue");
5041 }
5042 foreach my $param (@params) {
5043 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $par am->name);
5044 }
5045 $code .= join(", ", @args);
5046
5047 $code .= ")\n";
5048 $code .= "{\n";
5049 $code .= " if (!canInvokeCallback())\n";
5050 $code .= " return${defaultReturn};\n\n";
5051 $code .= " v8::HandleScope handleScope(m_isolate);\n\n";
5052 $code .= " v8::Handle<v8::Context> v8Context = toV8Context(execut ionContext(), m_world.get());\n";
5053 $code .= " if (v8Context.IsEmpty())\n";
5054 $code .= " return${defaultReturn};\n\n";
5055 $code .= " v8::Context::Scope scope(v8Context);\n";
5056
5057 my $thisObjectHandle = "";
5058 if ($callWithThisValue) {
5059 $code .= " v8::Handle<v8::Value> thisHandle = thisValue.v8Val ue();\n";
5060 $code .= " if (thisHandle.IsEmpty()) {\n";
5061 $code .= " if (!isScriptControllerTerminating())\n";
5062 $code .= " CRASH();\n";
5063 $code .= " return${defaultReturn};\n";
5064 $code .= " }\n";
5065 $code .= " ASSERT(thisHandle->IsObject());\n";
5066 $thisObjectHandle = "v8::Handle<v8::Object>::Cast(thisHandle), " ;
5067 }
5068 @args = ();
5069 foreach my $param (@params) {
5070 my $paramName = $param->name;
5071 $code .= NativeToJSValue($param->type, $param->extendedAttribute s, $paramName, " ", "v8::Handle<v8::Value> ${paramName}Handle =", "m_isolate" , "") . "\n";
5072 $code .= " if (${paramName}Handle.IsEmpty()) {\n";
5073 $code .= " if (!isScriptControllerTerminating())\n";
5074 $code .= " CRASH();\n";
5075 $code .= " return${defaultReturn};\n";
5076 $code .= " }\n";
5077 push(@args, "${paramName}Handle");
5078 }
5079
5080 if (scalar(@args) > 0) {
5081 $code .= " v8::Handle<v8::Value> argv[] = { ";
5082 $code .= join(", ", @args);
5083 $code .= " };\n\n";
5084 } else {
5085 $code .= " v8::Handle<v8::Value> *argv = 0;\n\n";
5086 }
5087 $code .= " ";
5088 if ($function->type eq "boolean") {
5089 $code .= "return ";
5090 }
5091 $code .= "invokeCallback(m_callback.newLocal(m_isolate), ${thisObjec tHandle}" . scalar(@args) . ", argv, executionContext(), m_isolate);\n";
5092 $code .= "}\n\n";
5093 $implementation{nameSpaceWebCore}->add($code);
5094 }
5095 }
5096 }
5097
5098 sub GenerateSpecialWrap
5099 {
5100 my $interface = shift;
5101 my $v8ClassName = shift;
5102 my $nativeType = GetNativeTypeForConversions($interface);
5103
5104 my $specialWrap = $interface->extendedAttributes->{"SpecialWrapFor"};
5105 my $isDocument = InheritsInterface($interface, "Document");
5106 if (!$specialWrap && !$isDocument) {
5107 return;
5108 }
5109
5110 my $code = "";
5111 $code .= <<END;
5112 v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creation Context, v8::Isolate* isolate)
5113 {
5114 ASSERT(impl);
5115 END
5116 if ($specialWrap) {
5117 foreach my $type (split(/\s*\|\s*/, $specialWrap)) {
5118 AddToImplIncludes("V8${type}.h");
5119 $code .= <<END;
5120 if (impl->is${type}())
5121 return wrap(to${type}(impl), creationContext, isolate);
5122 END
5123 }
5124 }
5125 $code .= <<END;
5126 v8::Handle<v8::Object> wrapper = ${v8ClassName}::createWrapper(impl, creatio nContext, isolate);
5127 END
5128 if ($isDocument) {
5129 AddToImplIncludes("bindings/v8/ScriptController.h");
5130 AddToImplIncludes("bindings/v8/V8WindowShell.h");
5131 $code .= <<END;
5132 if (wrapper.IsEmpty())
5133 return wrapper;
5134 DOMWrapperWorld* world = DOMWrapperWorld::current(isolate);
5135 if (world->isMainWorld()) {
5136 if (LocalFrame* frame = impl->frame())
5137 frame->script().windowShell(world)->updateDocumentWrapper(wrapper);
5138 }
5139 END
5140 }
5141 $code .= <<END;
5142 return wrapper;
5143 }
5144
5145 END
5146 $implementation{nameSpaceWebCore}->add($code);
5147 }
5148
5149 sub GenerateToV8Converters
5150 {
5151 my $interface = shift;
5152 my $v8ClassName = shift;
5153 my $interfaceName = $interface->name;
5154
5155 if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "T oV8")) {
5156 return;
5157 }
5158
5159 my $passRefPtrType = GetPassRefPtrType($interface);
5160
5161 my $wrapperConfiguration = "WrapperConfiguration::Independent";
5162 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")
5163 || InheritsExtendedAttribute($interface, "DependentLifetime")
5164 || NeedsVisitDOMWrapper($interface)) {
5165 $wrapperConfiguration = "WrapperConfiguration::Dependent";
5166 }
5167
5168 my $code = "";
5169 $code .= <<END;
5170 v8::Handle<v8::Object> ${v8ClassName}::createWrapper(${passRefPtrType} impl, v8: :Handle<v8::Object> creationContext, v8::Isolate* isolate)
5171 {
5172 ASSERT(impl);
5173 ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl.get(), isolate));
5174 if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) {
5175 const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObje ct(impl.get());
5176 // Might be a XXXConstructor::wrapperTypeInfo instead of an XXX::wrapper TypeInfo. These will both have
5177 // the same object de-ref functions, though, so use that as the basis of the check.
5178 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == wrapperTypeInfo.derefObjectFunction);
5179 }
5180
5181 END
5182
5183 if (InheritsInterface($interface, "Document")) {
5184 AddToImplIncludes("bindings/v8/ScriptController.h");
5185 AddToImplIncludes("core/frame/LocalFrame.h");
5186 $code .= <<END;
5187 if (LocalFrame* frame = impl->frame()) {
5188 if (frame->script().initializeMainWorld()) {
5189 // initializeMainWorld may have created a wrapper for the object, re try from the start.
5190 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper<${v8ClassN ame}>(impl.get(), isolate);
5191 if (!wrapper.IsEmpty())
5192 return wrapper;
5193 }
5194 }
5195 END
5196 }
5197
5198 $code .= <<END;
5199 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext , &wrapperTypeInfo, toInternalPointer(impl.get()), isolate);
5200 if (UNLIKELY(wrapper.IsEmpty()))
5201 return wrapper;
5202
5203 END
5204 if (InheritsInterface($interface, "AudioBuffer")) {
5205 AddToImplIncludes("modules/webaudio/AudioBuffer.h");
5206 $code .= <<END;
5207 for (unsigned i = 0, n = impl->numberOfChannels(); i < n; i++) {
5208 Float32Array* channelData = impl->getChannelData(i);
5209 channelData->buffer()->setDeallocationObserver(V8ArrayBufferDeallocation Observer::instanceTemplate());
5210 }
5211 END
5212 }
5213
5214
5215 $code .= <<END;
5216 installPerContextEnabledProperties(wrapper, impl.get(), isolate);
5217 V8DOMWrapper::associateObjectWithWrapper<$v8ClassName>(impl, &wrapperTypeInf o, wrapper, isolate, $wrapperConfiguration);
5218 return wrapper;
5219 }
5220
5221 END
5222 $implementation{nameSpaceWebCore}->add($code);
5223 }
5224
5225 sub GenerateSecurityCheckFunctions
5226 {
5227 my $interface = shift;
5228 my $implClassName = GetImplName($interface);
5229 my $v8ClassName = GetV8ClassName($interface);
5230
5231 AddToImplIncludes("bindings/v8/BindingSecurity.h");
5232 $implementation{nameSpaceInternal}->add(<<END);
5233 bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::Access Type type, v8::Local<v8::Value>)
5234 {
5235 $implClassName* imp = ${v8ClassName}::toNative(host);
5236 return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(), imp->frame(), DoNotReportSecurityError);
5237 }
5238
5239 END
5240 $implementation{nameSpaceInternal}->add(<<END);
5241 bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8 ::AccessType type, v8::Local<v8::Value>)
5242 {
5243 $implClassName* imp = ${v8ClassName}::toNative(host);
5244 return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(), imp->frame(), DoNotReportSecurityError);
5245 }
5246
5247 END
5248 }
5249
5250 sub GetNativeTypeForConversions
5251 {
5252 my $interface = shift;
5253 my $implClassName = GetImplName($interface);
5254 $implClassName = GetSVGTypeNeedingTearOff($interface->name) if IsSVGTypeNeed ingTearOff($interface->name);
5255 return $implClassName;
5256 }
5257
5258 sub GetNamespaceForInterface
5259 {
5260 my $interface = shift;
5261 return "WTF" if IsTypedArrayType($interface->name);
5262 return "WebCore";
5263 }
5264
5265 sub GenerateFunctionCallString
5266 {
5267 my $function = shift;
5268 my $numberOfParameters = shift;
5269 my $indent = shift;
5270 my $interface = shift;
5271 my $forMainWorldSuffix = shift;
5272 my $hasExceptionState = shift;
5273 my %replacements = @_;
5274
5275 my $interfaceName = $interface->name;
5276 my $implClassName = GetImplName($interface);
5277 my $name = GetImplName($function);
5278 my $returnType = $function->type;
5279 my $code = "";
5280 my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interf aceName =~ /List$/);
5281
5282 my $index = 0;
5283 my $humanFriendlyIndex = $index + 1;
5284
5285 my @arguments;
5286 my $functionName;
5287 my $implementedBy = $function->extendedAttributes->{"ImplementedBy"};
5288 if ($implementedBy) {
5289 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy) ;
5290 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedBy ImplName));
5291 if (!$function->isStatic) {
5292 $code .= " ASSERT(imp);\n";
5293 unshift(@arguments, "*imp");
5294 }
5295 $functionName = "${implementedByImplName}::${name}";
5296 } elsif ($function->isStatic) {
5297 $functionName = "${implClassName}::${name}";
5298 } else {
5299 $functionName = "imp->${name}";
5300 }
5301
5302 my $callWith = $function->extendedAttributes->{"CallWith"};
5303 my ($callWithArgs, $subCode) = GenerateCallWith($callWith, $indent, 1, $func tion);
5304 $code .= $subCode;
5305 unshift(@arguments, @$callWithArgs);
5306 $index += @$callWithArgs;
5307 $humanFriendlyIndex = $index + 1;
5308
5309 $numberOfParameters += @$callWithArgs;
5310
5311 foreach my $parameter (@{$function->parameters}) {
5312 if ($index eq $numberOfParameters) {
5313 last;
5314 }
5315 my $paramName = $parameter->name;
5316 my $paramType = $parameter->type;
5317
5318 if ($replacements{$paramName}) {
5319 push @arguments, $replacements{$paramName};
5320 } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceNam e =~ /List$/) {
5321 push @arguments, "$paramName->propertyReference()";
5322 if ($hasExceptionState) {
5323 $code .= <<END;
5324 if (!$paramName) {
5325 exceptionState.throwTypeError(\"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }'.\");
5326 exceptionState.throwIfNeeded();
5327 return;
5328 }
5329 END
5330 } else {
5331 $code .= <<END;
5332 if (!$paramName) {
5333 throwTypeError(ExceptionMessages::failedToExecute(\"$name\", \"$interfac eName\", \"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }' .\"), info.GetIsolate());
5334 return;
5335 }
5336 END
5337 }
5338 } elsif (IsNullableParameter($parameter)) {
5339 push @arguments, "${paramName}IsNull ? 0 : &$paramName";
5340 } elsif (IsCallbackInterface($paramType) or $paramType eq "NodeFilter" o r $paramType eq "XPathNSResolver") {
5341 push @arguments, "$paramName.release()";
5342 } else {
5343 push @arguments, $paramName;
5344 }
5345 $index++;
5346 $humanFriendlyIndex = $index + 1;
5347 }
5348
5349 # Support for returning a union type.
5350 if (IsUnionType($returnType)) {
5351 my $types = $returnType->unionMemberTypes;
5352 for my $i (0 .. scalar(@$types)-1) {
5353 my $unionMemberType = $types->[$i];
5354 my $unionMemberNativeType = GetNativeType($unionMemberType);
5355 my $unionMemberNumber = $i + 1;
5356 my $unionMemberVariable = "result" . $i;
5357 my $unionMemberEnabledVariable = "result" . $i . "Enabled";
5358 $code .= " bool ${unionMemberEnabledVariable} = false;\n";
5359 $code .= " ${unionMemberNativeType} ${unionMemberVariable};\n";
5360 push @arguments, $unionMemberEnabledVariable;
5361 push @arguments, $unionMemberVariable;
5362 }
5363 }
5364
5365 if ($function->extendedAttributes->{"RaisesException"}) {
5366 push @arguments, "exceptionState";
5367 }
5368
5369 my $functionString = "$functionName(" . join(", ", @arguments) . ")";
5370
5371 my $return = "result";
5372 my $returnIsRef = IsRefPtrType($returnType);
5373
5374 if ($returnType eq "void" || IsUnionType($returnType)) {
5375 $code .= $indent . "$functionString;\n";
5376 } elsif (ExtendedAttributeContains($callWith, "ScriptState") or $function->e xtendedAttributes->{"RaisesException"}) {
5377 my $nativeReturnType = GetNativeType($returnType, {}, "");
5378 $nativeReturnType = GetSVGWrappedTypeNeedingTearOff($returnType) if $isS VGTearOffType;
5379
5380 $code .= $indent . $nativeReturnType . " result = $functionString;\n";
5381 } else {
5382 # Can inline the function call into the return statement to avoid overhe ad of using a Ref<> temporary
5383 $return = $functionString;
5384 $returnIsRef = 0;
5385 }
5386
5387 if ($function->extendedAttributes->{"RaisesException"}) {
5388 $code .= $indent . "if (exceptionState.throwIfNeeded())\n";
5389 $code .= $indent . " return;\n";
5390 }
5391
5392 if (ExtendedAttributeContains($callWith, "ScriptState")) {
5393 $code .= $indent . "if (state.hadException()) {\n";
5394 $code .= $indent . " v8::Local<v8::Value> exception = state.exception ();\n";
5395 $code .= $indent . " state.clearException();\n";
5396 $code .= $indent . " throwError(exception, info.GetIsolate());\n";
5397 $code .= $indent . " return;\n";
5398 $code .= $indent . "}\n";
5399 }
5400
5401 if ($isSVGTearOffType) {
5402 AddToImplIncludes("V8$returnType.h");
5403 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h");
5404 my $svgNativeType = GetSVGTypeNeedingTearOff($returnType);
5405 # FIXME: Update for all ScriptWrappables.
5406 if (IsDOMNodeType($interfaceName)) {
5407 if ($forMainWorldSuffix eq "ForMainWorld") {
5408 $code .= $indent . "v8SetReturnValueForMainWorld(info, WTF::getP tr(${svgNativeType}::create($return)));\n";
5409 } else {
5410 $code .= $indent . "v8SetReturnValueFast(info, WTF::getPtr(${svg NativeType}::create($return)), imp);\n";
5411 }
5412 } else {
5413 $code .= $indent . "v8SetReturnValue${forMainWorldSuffix}(info, WTF: :getPtr(${svgNativeType}::create($return)));\n";
5414 }
5415 return $code;
5416 }
5417
5418 # If the implementing class is a POD type, commit changes
5419 if (IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$ /) {
5420 $code .= $indent . "wrapper->commitChange();\n";
5421 }
5422
5423 $return .= ".release()" if ($returnIsRef);
5424
5425 my $nativeValue;
5426 # FIXME: Update for all ScriptWrappables.
5427 if (IsDOMNodeType($interfaceName)) {
5428 $nativeValue = NativeToJSValue($function->type, $function->extendedAttri butes, $return, $indent, "", "info.GetIsolate()", "info", "imp", $forMainWorldSu ffix, "return");
5429 } else {
5430 $nativeValue = NativeToJSValue($function->type, $function->extendedAttri butes, $return, $indent, "", "info.GetIsolate()", "info", 0, $forMainWorldSuffix , "return");
5431 }
5432
5433 $code .= $nativeValue . "\n" if $nativeValue; # Skip blank line for void re turn type
5434
5435 return $code;
5436 }
5437
5438 sub GetNativeType
5439 {
5440 my $type = shift;
5441 my $extendedAttributes = shift;
5442 my $isParameter = shift;
5443
5444 my $svgNativeType = GetSVGTypeNeedingTearOff($type);
5445 if ($svgNativeType) {
5446 if ($svgNativeType =~ /List$/) {
5447 return "${svgNativeType}*";
5448 } else {
5449 return "RefPtr<${svgNativeType} >";
5450 }
5451 }
5452
5453 return "float" if $type eq "float";
5454 return "double" if $type eq "double";
5455 return "int" if $type eq "long" or $type eq "int" or $type eq "short" or $ty pe eq "byte";
5456 if ($type eq "unsigned long" or $type eq "unsigned int" or $type eq "unsigne d short" or $type eq "octet") {
5457 return "unsigned";
5458 }
5459 return "long long" if $type eq "long long";
5460 return "unsigned long long" if $type eq "unsigned long long";
5461 return "bool" if $type eq "boolean";
5462
5463 if (($type eq "DOMString" || IsEnumType($type)) and $isParameter) {
5464 my $mode = GetV8StringResourceMode($extendedAttributes);
5465 # FIXME: Add the case for 'elsif ($attributeOrParameter->extendedAttribu tes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes->{"Treat UndefinedAs"} eq "NullString"))'.
5466 return "V8StringResource<$mode>";
5467 }
5468
5469 return "String" if $type eq "DOMString" or IsEnumType($type);
5470
5471 return "ScriptPromise" if $type eq "Promise";
5472
5473 return "Range::CompareHow" if $type eq "CompareHow";
5474 return "DOMTimeStamp" if $type eq "DOMTimeStamp";
5475 return "double" if $type eq "Date";
5476 return "ScriptValue" if $type eq "any" or IsCallbackFunctionType($type);
5477 return "Dictionary" if $type eq "Dictionary";
5478
5479 die "UnionType is not supported" if IsUnionType($type);
5480
5481 if (IsTypedArrayType($type)) {
5482 return $isParameter ? "${type}*" : "RefPtr<${type}>";
5483 }
5484
5485 # We need to check [ImplementedAs] extended attribute for wrapper types.
5486 return "RefPtrWillBeRawPtr<$type>" if $type eq "XPathNSResolver"; # FIXME: Remove custom bindings for XPathNSResolver.
5487 if (IsWrapperType($type)) {
5488 my $interface = ParseInterface($type);
5489 my $implClassName = GetImplName($interface);
5490 if ($isParameter) {
5491 return "$implClassName*";
5492 } elsif (IsWillBeGarbageCollectedType($interface->name)) {
5493 return "RefPtrWillBeRawPtr<$implClassName>";
5494 } else {
5495 return "RefPtr<$implClassName>";
5496 }
5497 }
5498 return "RefPtr<$type>" if IsRefPtrType($type) and (not $isParameter or $nonW rapperTypes{$type});
5499
5500 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5501
5502 if ($arrayOrSequenceType) {
5503 my $nativeType = GetNativeType($arrayOrSequenceType);
5504 $nativeType .= " " if ($nativeType =~ />$/);
5505 return "Vector<${nativeType}>";
5506 }
5507
5508 # Default, assume native type is a pointer with same type name as idl type
5509 return "${type}*";
5510 }
5511
5512 sub GetNativeTypeForCallbacks
5513 {
5514 my $type = shift;
5515 return "const String&" if $type eq "DOMString";
5516 return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValu e";
5517 return "void" if $type eq "void";
5518
5519 # Callbacks use raw pointers, so pass isParameter = 1
5520 my $nativeType = GetNativeType($type, {}, "parameter");
5521 return "const $nativeType&" if $nativeType =~ /^Vector/;
5522 return $nativeType;
5523 }
5524
5525 sub JSValueToNativeStatement
5526 {
5527 my $type = shift;
5528 my $extendedAttributes = shift;
5529 my $argIndexOrZero = shift;
5530 my $jsValue = shift;
5531 my $variableName = shift;
5532 my $indent = shift;
5533 my $getIsolate = shift;
5534
5535 my $nativeType = GetNativeType($type, $extendedAttributes, "parameter");
5536 my $native_value = JSValueToNative($type, $extendedAttributes, $argIndexOrZe ro, $jsValue, $getIsolate);
5537 my $code = "";
5538 if ($type eq "DOMString" || IsEnumType($type)) {
5539 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8St ringResource/;
5540 if ($type eq "DOMString" or IsEnumType($type)) {
5541 $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType , $variableName, $native_value);\n"
5542 } else {
5543 $code .= $indent . "$nativeType $variableName($native_value, true);\ n";
5544 }
5545 } elsif (IsIntegerType($type)) {
5546 $code .= $indent . "V8TRYCATCH_EXCEPTION_VOID($nativeType, $variableName , $native_value, exceptionState);\n";
5547 } else {
5548 $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_ value);\n";
5549 }
5550 return $code;
5551 }
5552
5553
5554 sub JSValueToNative
5555 {
5556 my $type = shift;
5557 my $extendedAttributes = shift;
5558 # Argument position (1-indexed) or 0 if for a setter's value.
5559 my $argIndexOrZero = shift;
5560 my $value = shift;
5561 my $getIsolate = shift;
5562
5563 return "$value->BooleanValue()" if $type eq "boolean";
5564 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $t ype eq "double";
5565
5566 if (IsIntegerType($type)) {
5567 my $conversion = "to" . $integerTypeHash{$type} . "($value";
5568 if ($extendedAttributes->{"EnforceRange"}) {
5569 return "${conversion}, EnforceRange, exceptionState)";
5570 } else {
5571 return "${conversion}, exceptionState)";
5572 }
5573 }
5574 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "C ompareHow";
5575 return "toCoreDate($value)" if $type eq "Date";
5576
5577 if ($type eq "DOMString" or IsEnumType($type)) {
5578 return $value;
5579 }
5580
5581 if ($type eq "SerializedScriptValue") {
5582 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
5583 return "SerializedScriptValue::create($value, $getIsolate)";
5584 }
5585
5586 if ($type eq "Dictionary") {
5587 AddToImplIncludes("bindings/v8/Dictionary.h");
5588 return "Dictionary($value, $getIsolate)";
5589 }
5590
5591 if ($type eq "any" || IsCallbackFunctionType($type)) {
5592 AddToImplIncludes("bindings/v8/ScriptValue.h");
5593 return "ScriptValue($value, $getIsolate)";
5594 }
5595
5596 if ($type eq "Promise") {
5597 AddToImplIncludes("bindings/v8/ScriptPromise.h");
5598 return "ScriptPromise($value, $getIsolate)";
5599 }
5600
5601 if ($type eq "NodeFilter") {
5602 return "toNodeFilter($value, $getIsolate)";
5603 }
5604
5605 if ($type eq "Window") {
5606 return "toDOMWindow($value, $getIsolate)";
5607 }
5608
5609 if ($type eq "MediaQueryListListener") {
5610 AddToImplIncludes("core/css/MediaQueryListListener.h");
5611 return "MediaQueryListListener::create(ScriptValue(" . $value . ", $getI solate))";
5612 }
5613
5614 if ($type eq "EventTarget") {
5615 return "V8DOMWrapper::isDOMWrapper($value) ? toWrapperTypeInfo(v8::Handl e<v8::Object>::Cast($value))->toEventTarget(v8::Handle<v8::Object>::Cast($value) ) : 0";
5616 }
5617
5618 if (IsTypedArrayType($type)) {
5619 AddIncludesForType($type);
5620 return "$value->Is${type}() ? V8${type}::toNative(v8::Handle<v8::${type} >::Cast($value)) : 0"
5621 }
5622
5623 if ($type eq "XPathNSResolver") {
5624 return "toXPathNSResolver($value, $getIsolate)";
5625 }
5626
5627 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5628
5629 if ($arrayOrSequenceType) {
5630 if (IsRefPtrType($arrayOrSequenceType)) {
5631 AddToImplIncludes("V8${arrayOrSequenceType}.h");
5632 return "(toRefPtrNativeArray<${arrayOrSequenceType}, V8${arrayOrSequ enceType}>($value, $argIndexOrZero, $getIsolate))";
5633 }
5634 return "toNativeArray<" . GetNativeType($arrayOrSequenceType) . ">($valu e, $argIndexOrZero, $getIsolate)";
5635 }
5636
5637 AddIncludesForType($type);
5638
5639 AddToImplIncludes("V8${type}.h");
5640 return "V8${type}::toNativeWithTypeCheck(info.GetIsolate(), $value)";
5641 }
5642
5643 sub IsUnionType
5644 {
5645 my $type = shift; # string or UnionType
5646 if(ref($type) eq "UnionType") {
5647 die "Currently only 2 values of non-union type is supported as union typ e.\n" unless @{$type->unionMemberTypes} == 2;
5648 return 1;
5649 }
5650 return 0;
5651 }
5652
5653 sub IsWrapperType
5654 {
5655 my $type = shift;
5656 return 0 if GetArrayType($type);
5657 return 0 if GetSequenceType($type);
5658 return 0 if IsCallbackFunctionType($type);
5659 return 0 if IsEnumType($type);
5660 return 0 if IsPrimitiveType($type);
5661 return 0 if $type eq "Promise";
5662 return !$nonWrapperTypes{$type};
5663 }
5664
5665 sub IsCallbackInterface
5666 {
5667 my $type = shift;
5668 return 0 unless IsWrapperType($type);
5669 return 0 if IsTypedArrayType($type);
5670
5671 my $idlFile = IDLFileForInterface($type)
5672 or die("Could NOT find IDL file for interface \"$type\"!\n");
5673
5674 open FILE, "<", $idlFile;
5675 my @lines = <FILE>;
5676 close FILE;
5677
5678 my $fileContents = join('', @lines);
5679 return ($fileContents =~ /callback\s+interface\s+(\w+)\s*{/gs);
5680 }
5681
5682 sub GetNativeTypeOfTypedArray
5683 {
5684 my $interface = shift;
5685 my $interfaceName = $interface->name;
5686 die "TypedArray of unknown type is found" unless $typedArrayHash{$interface- >name};
5687 return @{$typedArrayHash{$interface->name}};
5688 }
5689
5690 sub IsDOMNodeType
5691 {
5692 my $type = shift;
5693
5694 return 1 if $domNodeTypes{$type};
5695 return 1 if $type =~ /^HTML.*Element$/;
5696 return 1 if $type =~ /^SVG.*Element$/;
5697
5698 return 0;
5699 }
5700
5701
5702 sub NativeToJSValue
5703 {
5704 my $type = shift;
5705 my $extendedAttributes = shift;
5706 my $nativeValue = shift;
5707 my $indent = shift; # added before every line
5708 my $receiver = shift; # "return" or "<variableName> ="
5709 my $getIsolate = shift;
5710 die "An Isolate is mandatory for native value => JS value conversion." unles s $getIsolate;
5711 my $getCallbackInfo = shift || "";
5712 my $creationContext = $getCallbackInfo ? "${getCallbackInfo}.Holder()" : "v8 ::Handle<v8::Object>()";
5713 my $getScriptWrappable = shift || "";
5714 my $forMainWorldSuffix = shift || "";
5715 my $returnValueArg = shift || 0;
5716 my $isReturnValue = $returnValueArg eq "return";
5717
5718 if (IsUnionType($type)) {
5719 my $types = $type->unionMemberTypes;
5720 my @codes = ();
5721 for my $i (0 .. scalar(@$types)-1) {
5722 my $unionMemberType = $types->[$i];
5723 my $unionMemberNumber = $i + 1;
5724 my $unionMemberVariable = $nativeValue . $i;
5725 my $unionMemberEnabledVariable = $nativeValue . $i . "Enabled";
5726 my $unionMemberNativeValue = $unionMemberVariable;
5727 $unionMemberNativeValue .= ".release()" if (IsRefPtrType($unionMembe rType));
5728 my $returnJSValueCode = NativeToJSValue($unionMemberType, $extendedA ttributes, $unionMemberNativeValue, $indent . " ", $receiver, $getIsolate, $g etCallbackInfo, $getScriptWrappable, $forMainWorldSuffix, $returnValueArg);
5729 my $code = "";
5730 if ($isReturnValue) {
5731 $code .= "${indent}if (${unionMemberEnabledVariable}) {\n";
5732 $code .= "${returnJSValueCode}\n";
5733 $code .= "${indent} return;\n";
5734 $code .= "${indent}}";
5735 } else {
5736 $code .= "${indent}if (${unionMemberEnabledVariable})\n";
5737 $code .= "${returnJSValueCode}";
5738 }
5739 push @codes, $code;
5740 }
5741 if ($isReturnValue) {
5742 # Fall back to returning null if none of the union members results a re returned.
5743 push @codes, "${indent}v8SetReturnValueNull(${getCallbackInfo});";
5744 }
5745 return join "\n", @codes;
5746 }
5747
5748 if ($type eq "boolean") {
5749 return "${indent}v8SetReturnValueBool(${getCallbackInfo}, ${nativeValue} );" if $isReturnValue;
5750 return "$indent$receiver v8Boolean($nativeValue, $getIsolate);";
5751 }
5752
5753 if ($type eq "void") { # equivalent to v8Undefined()
5754 return "" if $isReturnValue;
5755 return "$indent$receiver v8Undefined();"
5756 }
5757
5758 # HTML5 says that unsigned reflected attributes should be in the range
5759 # [0, 2^31). When a value isn't in this range, a default value (or 0)
5760 # should be returned instead.
5761 if ($extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
5762 $nativeValue =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
5763 return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, std::max(0 , ${nativeValue}));" if $isReturnValue;
5764 return "$indent$receiver v8::Integer::NewFromUnsigned($getIsolate, std:: max(0, " . $nativeValue . "));";
5765 }
5766
5767 my $nativeType = GetNativeType($type);
5768 if ($nativeType eq "int") {
5769 return "${indent}v8SetReturnValueInt(${getCallbackInfo}, ${nativeValue}) ;" if $isReturnValue;
5770 return "$indent$receiver v8::Integer::New($getIsolate, $nativeValue);";
5771 }
5772
5773 if ($nativeType eq "unsigned") {
5774 return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, ${nativeVa lue});" if $isReturnValue;
5775 return "$indent$receiver v8::Integer::NewFromUnsigned($getIsolate, $nati veValue);";
5776 }
5777
5778 if ($type eq "Date") {
5779 return "${indent}v8SetReturnValue(${getCallbackInfo}, v8DateOrNull($nati veValue, $getIsolate));" if $isReturnValue;
5780 return "$indent$receiver v8DateOrNull($nativeValue, $getIsolate);"
5781 }
5782
5783 # long long and unsigned long long are not representable in ECMAScript.
5784 if ($type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTi meStamp") {
5785 return "${indent}v8SetReturnValue(${getCallbackInfo}, static_cast<double >($nativeValue));" if $isReturnValue;
5786 return "$indent$receiver v8::Number::New($getIsolate, static_cast<double >($nativeValue));";
5787 }
5788
5789 if ($type eq "DOMString" && $extendedAttributes->{"ReflectOnly"}) {
5790 my $code = "${indent}String resultValue = ${nativeValue};\n";
5791 $code .= GenerateReflectOnlyCheck($extendedAttributes, ${indent});
5792 return "${code}${indent}v8SetReturnValueString(${getCallbackInfo}, resul tValue, $getIsolate);" if $isReturnValue;
5793 return "${code}$indent$receiver resultValue";
5794 }
5795
5796 my $conv = $extendedAttributes->{"TreatReturnedNullStringAs"};
5797 if (($type eq "DOMString" || IsEnumType($type)) && $isReturnValue) {
5798 my $functionSuffix = "";
5799 if (defined $conv) {
5800 if ($conv eq "Null") {
5801 $functionSuffix = "OrNull";
5802 } elsif ($conv eq "Undefined") {
5803 $functionSuffix = "OrUndefined";
5804 } else {
5805 die "Unknown value for TreatReturnedNullStringAs extended attrib ute";
5806 }
5807 }
5808 return "${indent}v8SetReturnValueString${functionSuffix}(${getCallbackIn fo}, $nativeValue, $getIsolate);";
5809 }
5810
5811 if ($type eq "DOMString" or IsEnumType($type)) {
5812 my $returnValue = "";
5813 if (defined $conv) {
5814 if ($conv eq "Null") {
5815 $returnValue = "v8StringOrNull($nativeValue, $getIsolate)";
5816 } elsif ($conv eq "Undefined") {
5817 $returnValue = "v8StringOrUndefined($nativeValue, $getIsolate)";
5818 } else {
5819 die "Unknown value for TreatReturnedNullStringAs extended attrib ute";
5820 }
5821 } else {
5822 $returnValue = "v8String($getIsolate, $nativeValue)";
5823 }
5824 return "$indent$receiver $returnValue;";
5825 }
5826
5827 if (IsPrimitiveType($type)) {
5828 die "unexpected type $type" if not ($type eq "float" or $type eq "double ");
5829 return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
5830 return "$indent$receiver v8::Number::New($getIsolate, $nativeValue);";
5831 }
5832
5833 if ($nativeType eq "ScriptValue" or $nativeType eq "ScriptPromise") {
5834 return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue}.v8V alue());" if $isReturnValue;
5835 return "$indent$receiver $nativeValue.v8Value();";
5836 }
5837
5838 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5839
5840 if ($arrayOrSequenceType) {
5841 if (IsRefPtrType($arrayOrSequenceType)) {
5842 AddIncludesForType($arrayOrSequenceType);
5843 }
5844 return "${indent}v8SetReturnValue(${getCallbackInfo}, v8Array($nativeVal ue, $getIsolate));" if $isReturnValue;
5845 return "$indent$receiver v8Array($nativeValue, $getIsolate);";
5846 }
5847
5848 AddIncludesForType($type);
5849
5850 if ($type eq "SerializedScriptValue") {
5851 my $returnValue = "$nativeValue ? $nativeValue->deserialize() : v8::Hand le<v8::Value>(v8::Null($getIsolate))";
5852 return "${indent}v8SetReturnValue(${getCallbackInfo}, $returnValue);" if $isReturnValue;
5853 return "$indent$receiver $returnValue;";
5854 }
5855
5856 if ($getScriptWrappable) {
5857 # FIXME: Use safe handles
5858 if ($isReturnValue) {
5859 if ($forMainWorldSuffix eq "ForMainWorld") {
5860 return "${indent}v8SetReturnValueForMainWorld(${getCallbackInfo} , $nativeValue);";
5861 }
5862 return "${indent}v8SetReturnValueFast(${getCallbackInfo}, $nativeVal ue, $getScriptWrappable);";
5863 }
5864 }
5865 # FIXME: Use safe handles
5866 return "${indent}v8SetReturnValue(${getCallbackInfo}, $nativeValue);" if $is ReturnValue;
5867 return "$indent$receiver toV8($nativeValue, $creationContext, $getIsolate);" ;
5868 }
5869
5870 sub WriteData
5871 {
5872 my $object = shift;
5873 my $interface = shift;
5874 my $outputDirectory = shift;
5875
5876 my $name = $interface->name;
5877 my $headerFileName = "$outputDirectory/V8$name.h";
5878 my $implFileName = "$outputDirectory/V8$name.cpp";
5879
5880 my @includes = ();
5881 foreach my $include (keys %implIncludes) {
5882 push @includes, "\"$include\"";
5883 }
5884
5885 #FIXME: do not treat main header special
5886 my $mainInclude = "\"V8$name.h\"";
5887 foreach my $include (sort @includes) {
5888 $implementation{includes}->add("#include $include\n") unless $include eq $mainInclude;
5889 }
5890 $implementation{includes}->add("\n") unless $interface->isCallback;
5891 WriteFileIfChanged($implFileName, $implementation{root}->toString());
5892
5893 %implIncludes = ();
5894
5895 WriteFileIfChanged($headerFileName, $header{root}->toString());
5896 }
5897
5898 sub ConvertToV8StringResource
5899 {
5900 my $attributeOrParameter = shift;
5901 my $nativeType = shift;
5902 my $variableName = shift;
5903 my $value = shift;
5904
5905 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8String Resource/;
5906 if ($attributeOrParameter->type eq "DOMString" or IsEnumType($attributeOrPar ameter->type)) {
5907 return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $value);"
5908 } else {
5909 return "$nativeType $variableName($value, true);";
5910 }
5911 }
5912
5913 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
5914 sub GetRuntimeEnabledFunctionName
5915 {
5916 my $signature = shift;
5917
5918 # Given [RuntimeEnabled=FeatureName],
5919 # return RuntimeEnabledFeatures::{featureName}Enabled;
5920 my $featureName = ToMethodName($signature->extendedAttributes->{"RuntimeEnab led"});
5921 return "RuntimeEnabledFeatures::${featureName}Enabled";
5922 }
5923
5924 sub GetContextEnabledFunctionName
5925 {
5926 my $signature = shift;
5927
5928 # Given [PerContextEnabled=FeatureName],
5929 # return ContextFeatures::{featureName}Enabled
5930 my $featureName = ToMethodName($signature->extendedAttributes->{"PerContextE nabled"});
5931 return "ContextFeatures::${featureName}Enabled";
5932 }
5933
5934 sub GetPassRefPtrType
5935 {
5936 my $interface = shift;
5937 my $nativeType = GetNativeTypeForConversions($interface);
5938
5939 my $willBe = IsWillBeGarbageCollectedType($interface->name) ? "WillBeRawPtr" : "";
5940 my $extraSpace = $nativeType =~ />$/ ? " " : "";
5941 return "PassRefPtr${willBe}<${nativeType}${extraSpace}>";
5942 }
5943
5944 sub WriteFileIfChanged
5945 {
5946 my $fileName = shift;
5947 my $contents = shift;
5948
5949 if (-f $fileName && $writeFileOnlyIfChanged) {
5950 open FH, "<", $fileName or die "Couldn't open $fileName: $!\n";
5951 my @lines = <FH>;
5952 my $oldContents = join "", @lines;
5953 close FH;
5954 return if $contents eq $oldContents;
5955 }
5956 open FH, ">", $fileName or die "Couldn't open $fileName: $!\n";
5957 print FH $contents;
5958 close FH;
5959 }
5960
5961 sub ForAllParents
5962 {
5963 my $interface = shift;
5964 my $beforeRecursion = shift;
5965 my $afterRecursion = shift;
5966
5967 my $recurse;
5968 $recurse = sub {
5969 my $currentInterface = shift;
5970
5971 if ($currentInterface->parent) {
5972 my $parentInterface = ParseInterface($currentInterface->parent);
5973 if ($beforeRecursion) {
5974 &$beforeRecursion($parentInterface) eq 'prune' and return;
5975 }
5976 &$recurse($parentInterface);
5977 &$afterRecursion($parentInterface) if $afterRecursion;
5978 }
5979 };
5980
5981 &$recurse($interface);
5982 }
5983
5984 sub IsPrimitiveType
5985 {
5986 my $type = shift;
5987
5988 return 1 if $integerTypeHash{$type};
5989 return 1 if $primitiveTypeHash{$type};
5990 return 0;
5991 }
5992
5993 sub IsIntegerType
5994 {
5995 my $type = shift;
5996
5997 return 1 if $integerTypeHash{$type};
5998 return 0;
5999 }
6000
6001 sub IsCallbackFunctionType
6002 {
6003 my $type = shift;
6004
6005 return 1 if $callbackFunctionTypeHash{$type};
6006 return 0;
6007 }
6008
6009 sub IsEnumType
6010 {
6011 my $type = shift;
6012
6013 return 1 if $enumTypeHash{$type};
6014 return 0;
6015 }
6016
6017 sub ValidEnumValues
6018 {
6019 my $type = shift;
6020
6021 return @{$enumTypeHash{$type}};
6022 }
6023
6024 sub IsSVGTypeNeedingTearOff
6025 {
6026 my $type = shift;
6027
6028 return 1 if $svgTypeNeedingTearOff{$type};
6029 return 0;
6030 }
6031
6032 sub IsTypedArrayType
6033 {
6034 my $type = shift;
6035 return 1 if $typedArrayHash{$type};
6036 return 0;
6037 }
6038
6039 sub IsWillBeGarbageCollectedType
6040 {
6041 my $interfaceName = shift;
6042 return 0 unless IsWrapperType($interfaceName);
6043 my $interface = ParseInterface($interfaceName);
6044 return InheritsExtendedAttribute($interface, "WillBeGarbageCollected");
6045 }
6046
6047 sub IsRefPtrType
6048 {
6049 my $type = shift;
6050
6051 return 0 if $type eq "any";
6052 return 0 if IsPrimitiveType($type);
6053 return 0 if GetArrayType($type);
6054 return 0 if GetSequenceType($type);
6055 return 0 if $type eq "Promise";
6056 return 0 if IsCallbackFunctionType($type);
6057 return 0 if IsEnumType($type);
6058 return 0 if IsUnionType($type);
6059 return 0 if $type eq "Dictionary";
6060
6061 return 1;
6062 }
6063
6064 sub IsNullableParameter
6065 {
6066 my $parameter = shift;
6067
6068 return $parameter->isNullable && !IsRefPtrType($parameter->type) && $paramet er->type ne "Dictionary";
6069 }
6070
6071 sub GetSVGTypeNeedingTearOff
6072 {
6073 my $type = shift;
6074
6075 return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type} ;
6076 return undef;
6077 }
6078
6079 sub GetSVGWrappedTypeNeedingTearOff
6080 {
6081 my $type = shift;
6082
6083 my $svgTypeNeedingTearOff = GetSVGTypeNeedingTearOff($type);
6084 return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff;
6085
6086 if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) {
6087 $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//;
6088 } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) {
6089 $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//;
6090 } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) {
6091 $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//;
6092 } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) {
6093 $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//;
6094 }
6095
6096 $svgTypeNeedingTearOff =~ s/>//;
6097 return $svgTypeNeedingTearOff;
6098 }
6099
6100 sub IsSVGAnimatedType
6101 {
6102 my $type = shift;
6103
6104 return $type =~ /^SVGAnimated/;
6105 }
6106
6107 sub SVGTypeNeedsToHoldContextElement
6108 {
6109 my $type = shift;
6110
6111 return IsSVGTypeNeedingTearOff($type) || IsSVGAnimatedType($type);
6112 }
6113
6114 sub GetSequenceType
6115 {
6116 my $type = shift;
6117
6118 return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/;
6119 return "";
6120 }
6121
6122 sub GetArrayType
6123 {
6124 my $type = shift;
6125
6126 return $1 if $type =~ /^([\w\d_\s]+)\[\]/;
6127 return "";
6128 }
6129
6130 sub GetArrayOrSequenceType
6131 {
6132 my $type = shift;
6133
6134 return GetArrayType($type) || GetSequenceType($type);
6135 }
6136
6137 sub AssertNotSequenceType
6138 {
6139 my $type = shift;
6140 die "Sequences must not be used as the type of an attribute, constant or exc eption field." if GetSequenceType($type);
6141 }
6142
6143 sub FirstLetterToUpperCase
6144 {
6145 my $param = shift;
6146 my $ret = ucfirst($param);
6147 # Capitalize initial acronym, e.g., xml -> setXML
6148 $ret =~ s/Xml/XML/ if $ret =~ /^Xml/;
6149 $ret =~ s/Css/CSS/ if $ret =~ /^Css/;
6150 $ret =~ s/Html/HTML/ if $ret =~ /^Html/;
6151 $ret =~ s/Ime/IME/ if $ret =~ /^Ime/;
6152 $ret =~ s/Svg/SVG/ if $ret =~ /^Svg/;
6153 return $ret;
6154 }
6155
6156 # URL becomes url, but SetURL becomes setURL.
6157 sub ToMethodName
6158 {
6159 my $param = shift;
6160 my $ret = lcfirst($param);
6161 $ret =~ s/hTML/html/ if $ret =~ /^hTML/;
6162 $ret =~ s/iME/ime/ if $ret =~ /^iME/;
6163 $ret =~ s/uRL/url/ if $ret =~ /^uRL/;
6164 $ret =~ s/jS/js/ if $ret =~ /^jS/;
6165 $ret =~ s/xML/xml/ if $ret =~ /^xML/;
6166 $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/;
6167 $ret =~ s/cSS/css/ if $ret =~ /^cSS/;
6168
6169 # For HTML5 FileSystem API Flags attributes.
6170 # (create is widely used to instantiate an object and must be avoided.)
6171 $ret =~ s/^create/isCreate/ if $ret =~ /^create$/;
6172 $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/;
6173
6174 return $ret;
6175 }
6176
6177 sub NamespaceForAttributeName
6178 {
6179 my ($interfaceName, $attributeName) = @_;
6180 return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$ attributeName};
6181 return "HTMLNames";
6182 }
6183
6184 # Identifies overloaded functions and for each function adds an array with
6185 # links to its respective overloads (including itself).
6186 sub LinkOverloadedFunctions
6187 {
6188 my $interface = shift;
6189
6190 my %nameToFunctionsMap = ();
6191 foreach my $function (@{$interface->functions}) {
6192 my $name = $function->name;
6193 $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name} or !$name; # Nameless functions cannot be overloaded
6194 push(@{$nameToFunctionsMap{$name}}, $function);
6195 $function->{overloads} = $nameToFunctionsMap{$name};
6196 $function->{overloadIndex} = @{$nameToFunctionsMap{$name}};
6197 }
6198 }
6199
6200 sub AttributeNameForGetterAndSetter
6201 {
6202 my $attribute = shift;
6203
6204 my $attributeName = GetImplName($attribute);
6205 if ($attribute->extendedAttributes->{"ImplementedAs"}) {
6206 $attributeName = $attribute->extendedAttributes->{"ImplementedAs"};
6207 }
6208 my $attributeType = $attribute->type;
6209
6210 return $attributeName;
6211 }
6212
6213 sub ContentAttributeName
6214 {
6215 my ($interfaceName, $attribute) = @_;
6216
6217 my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"};
6218 return undef if !$contentAttributeName;
6219
6220 $contentAttributeName = lc AttributeNameForGetterAndSetter($attribute) if $c ontentAttributeName eq "VALUE_IS_MISSING";
6221
6222 my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeN ame);
6223
6224 AddToImplIncludes("${namespace}.h");
6225 # Attr (not Attribute) used in core content attributes
6226 return "${namespace}::${contentAttributeName}Attr";
6227 }
6228
6229 sub GetterExpression
6230 {
6231 my ($interfaceName, $attribute) = @_;
6232
6233 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute);
6234
6235 if (!$contentAttributeName) {
6236 return (ToMethodName(AttributeNameForGetterAndSetter($attribute)));
6237 }
6238
6239 my $functionName;
6240 if ($attribute->extendedAttributes->{"URL"}) {
6241 $functionName = "getURLAttribute";
6242 } elsif ($attribute->type eq "boolean") {
6243 $functionName = "fastHasAttribute";
6244 } elsif ($attribute->type eq "long") {
6245 $functionName = "getIntegralAttribute";
6246 } elsif ($attribute->type eq "unsigned long") {
6247 $functionName = "getUnsignedIntegralAttribute";
6248 } else {
6249 if ($contentAttributeName eq "HTMLNames::idAttr") {
6250 $functionName = "getIdAttribute";
6251 $contentAttributeName = "";
6252 } elsif ($contentAttributeName eq "HTMLNames::nameAttr") {
6253 $functionName = "getNameAttribute";
6254 $contentAttributeName = "";
6255 } elsif ($contentAttributeName eq "HTMLNames::classAttr") {
6256 $functionName = "getClassAttribute";
6257 $contentAttributeName = "";
6258 } else {
6259 # We cannot use fast attributes for animated SVG types.
6260 $functionName = IsSVGAnimatedType($attribute->type) ? "getAttribute" : "fastGetAttribute";
6261 }
6262 }
6263
6264 return ($functionName, $contentAttributeName);
6265 }
6266
6267 sub SetterExpression
6268 {
6269 my ($interfaceName, $attribute) = @_;
6270
6271 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute);
6272
6273 if (!$contentAttributeName) {
6274 return ("set" . FirstLetterToUpperCase(AttributeNameForGetterAndSetter($ attribute)));
6275 }
6276
6277 my $functionName;
6278 if ($attribute->type eq "boolean") {
6279 $functionName = "setBooleanAttribute";
6280 } elsif ($attribute->type eq "long") {
6281 $functionName = "setIntegralAttribute";
6282 } elsif ($attribute->type eq "unsigned long") {
6283 $functionName = "setUnsignedIntegralAttribute";
6284 } else {
6285 $functionName = "setAttribute";
6286 }
6287
6288 return ($functionName, $contentAttributeName);
6289 }
6290
6291 sub GenerateConditionalString
6292 {
6293 my $node = shift;
6294
6295 my $conditional = $node->extendedAttributes->{"Conditional"};
6296 if ($conditional) {
6297 return GenerateConditionalStringFromAttributeValue($conditional);
6298 } else {
6299 return "";
6300 }
6301 }
6302
6303 sub GenerateConditionalStringFromAttributeValue
6304 {
6305 my $conditional = shift;
6306
6307 my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : '' ));
6308 if ($operator) {
6309 # Avoid duplicated conditions.
6310 my %conditions;
6311 map { $conditions{$_} = 1 } split('\\' . $operator, $conditional);
6312 return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %condi tions) . ")";
6313 } else {
6314 return "ENABLE(" . $conditional . ")";
6315 }
6316 }
6317
6318 sub GenerateCompileTimeCheckForEnumsIfNeeded
6319 {
6320 my $interface = shift;
6321 my $implClassName = GetImplName($interface);
6322 my @checks = ();
6323 # If necessary, check that all constants are available as enums with the sam e value.
6324 if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface ->constants}) {
6325 foreach my $constant (@{$interface->constants}) {
6326 my $reflect = $constant->extendedAttributes->{"Reflect"};
6327 my $name = $reflect ? $reflect : $constant->name;
6328 my $value = $constant->value;
6329
6330 if ($constant->extendedAttributes->{"ImplementedBy"}) {
6331 my $implementedByImplName = GetImplNameFromImplementedBy($consta nt->extendedAttributes->{"ImplementedBy"});
6332 push(@checks, " COMPILE_ASSERT($value == " . $implementedByIm plName . "::$name, TheValueOf${implClassName}_${name}DoesntMatchWithImplementati on);\n");
6333 } else {
6334 push(@checks, " COMPILE_ASSERT($value == ${implClassName}::$n ame, TheValueOf${implClassName}_${name}DoesntMatchWithImplementation);\n");
6335 }
6336 }
6337 }
6338 return @checks;
6339 }
6340
6341 sub GenerateReflectOnlyCheck
6342 {
6343 my $extendedAttributes = shift;
6344 my $indent = shift;
6345
6346 my $attributeValueList = $extendedAttributes->{"ReflectOnly"};
6347 my @knownValues = split(quotemeta("|"), $attributeValueList);
6348
6349 my $missingValueDefault = $extendedAttributes->{"ReflectMissing"};
6350 if ($missingValueDefault) {
6351 if (!grep { $_ eq $missingValueDefault } @knownValues) {
6352 die "The [ReflectMissing] attribute value '${missingValueDefault}' i s not a known value ";
6353 }
6354 $missingValueDefault = "resultValue = \"${missingValueDefault}\"";
6355 } else {
6356 $missingValueDefault = "";
6357 }
6358
6359 my $invalidValueDefault = $extendedAttributes->{"ReflectInvalid"};
6360 if ($invalidValueDefault) {
6361 if (!grep { $_ eq $invalidValueDefault } @knownValues) {
6362 die "The [ReflectInvalid] attribute value '${invalidValueDefault}' i s not a known value ";
6363 }
6364 $invalidValueDefault = "resultValue = \"${invalidValueDefault}\"";
6365 } else {
6366 $invalidValueDefault = "resultValue = \"\"";
6367 }
6368
6369 my @normalizeAttributeCode = ();
6370
6371 # Attributes without a value (div empty-attribute>) can be
6372 # separately reflected to some value.
6373
6374 my $isAttributeValueMissing = "resultValue.isEmpty()";
6375 my $emptyValueDefault = $extendedAttributes->{"ReflectEmpty"};
6376 if ($emptyValueDefault) {
6377 if (!grep { $_ eq $emptyValueDefault } @knownValues) {
6378 die "The [ReflectEmpty] attribute value '${emptyValueDefault}' is no t a known value ";
6379 }
6380 $isAttributeValueMissing = "resultValue.isNull()";
6381 push(@normalizeAttributeCode, "${indent}} else if (resultValue.isEmpty() ) {");
6382 push(@normalizeAttributeCode, "${indent} resultValue = \"$emptyValueD efault\";");
6383 }
6384
6385 # Attribute is limited to only known values: check that the attribute
6386 # value is one of those..and if not, set it to the empty string.
6387 # ( http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known -values )
6388 #
6389 foreach my $knownValue (@knownValues) {
6390 push(@normalizeAttributeCode, "${indent}} else if (equalIgnoringCase(res ultValue, \"$knownValue\")) {");
6391 push(@normalizeAttributeCode, "${indent} resultValue = \"$knownValue\ ";");
6392 }
6393 my $normalizeAttributeValue = join("\n", @normalizeAttributeCode);
6394 my $code .= <<END;
6395 ${indent}if ($isAttributeValueMissing) {
6396 ${indent} $missingValueDefault;
6397 ${normalizeAttributeValue}
6398 ${indent}} else {
6399 ${indent} $invalidValueDefault;
6400 ${indent}}
6401 END
6402 return "${code}";
6403 }
6404
6405 sub ExtendedAttributeContains
6406 {
6407 my $extendedAttributeValue = shift;
6408 return 0 unless $extendedAttributeValue;
6409 my $keyword = shift;
6410
6411 my @extendedAttributeValues = split /\s*(\&|\|)\s*/, $extendedAttributeValue ;
6412 return grep { $_ eq $keyword } @extendedAttributeValues;
6413 }
6414
6415 sub InheritsInterface
6416 {
6417 my $interface = shift;
6418 my $interfaceName = shift;
6419 my $found = 0;
6420
6421 return 1 if $interfaceName eq $interface->name;
6422 ForAllParents($interface, sub {
6423 my $currentInterface = shift;
6424 if ($currentInterface->name eq $interfaceName) {
6425 $found = 1;
6426 }
6427 return 1 if $found;
6428 }, 0);
6429
6430 return $found;
6431 }
6432
6433 sub InheritsExtendedAttribute
6434 {
6435 my $interface = shift;
6436 my $extendedAttribute = shift;
6437 my $found = 0;
6438
6439 return 1 if $interface->extendedAttributes->{$extendedAttribute};
6440 ForAllParents($interface, sub {
6441 my $currentInterface = shift;
6442 if ($currentInterface->extendedAttributes->{$extendedAttribute}) {
6443 $found = 1;
6444 }
6445 return 1 if $found;
6446 }, 0);
6447
6448 return $found;
6449 }
6450
6451 sub NeedsSpecialWrap
6452 {
6453 my $interface = shift;
6454
6455 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Cust om"}, "ToV8");
6456 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Cust om"}, "Wrap");
6457 return 1 if $interface->extendedAttributes->{"SpecialWrapFor"};
6458 return 1 if InheritsInterface($interface, "Document");
6459
6460 return 0;
6461 }
6462
6463 sub HasExceptionRaisingParameter
6464 {
6465 my $function = shift;
6466
6467 foreach my $parameter (@{$function->parameters}) {
6468 if ($parameter->type eq "SerializedScriptValue") {
6469 return 1;
6470 } elsif (IsIntegerType($parameter->type)) {
6471 return 1;
6472 }
6473 }
6474 return 0;
6475 }
6476
6477 1;
OLDNEW
« no previous file with comments | « Source/bindings/scripts/blink_idl_parser.py ('k') | Source/bindings/scripts/code_generator_v8.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698