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

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

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

Powered by Google App Engine
This is Rietveld 408576698