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

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: Move to unstable 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"};
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/ExceptionState.h");
1454 $code .= " ExceptionState es(info.GetIsolate());\n";
1455 }
1456
1457 if ($isNullable) {
1458 $code .= " bool isNull = false;\n";
1459 }
1460
1461 my $returnType = $attribute->type;
1462 my $getterString;
1463
1464 my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute );
1465 push(@arguments, "isNull") if $isNullable;
1466 push(@arguments, "es") if $useExceptions;
1467 if ($attribute->extendedAttributes->{"ImplementedBy"}) {
1468 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"};
1469 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy) ;
1470 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedBy ImplName));
1471 unshift(@arguments, "imp") if !$attribute->isStatic;
1472 $functionName = "${implementedByImplName}::${functionName}";
1473 } elsif ($attribute->isStatic) {
1474 $functionName = "${implClassName}::${functionName}";
1475 } else {
1476 $functionName = "imp->${functionName}";
1477 }
1478 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"Cal lWith"}, " ", 0);
1479 $code .= $subCode;
1480 unshift(@arguments, @$arg);
1481 $getterString = "${functionName}(" . join(", ", @arguments) . ")";
1482
1483 my $expression;
1484 if ($attribute->type eq "EventHandler" && $interface->name eq "Window") {
1485 $code .= " if (!imp->document())\n";
1486 $code .= " return;\n";
1487 }
1488
1489 if ($useExceptions || $isNullable) {
1490 if ($nativeType =~ /^V8StringResource/) {
1491 $code .= " " . ConvertToV8StringResource($attribute, $nativeType, "v", $getterString) . ";\n";
1492 } else {
1493 $code .= " $nativeType v = $getterString;\n";
1494 }
1495
1496 if ($isNullable) {
1497 $code .= " if (isNull) {\n";
1498 $code .= " v8SetReturnValueNull(info);\n";
1499 $code .= " return;\n";
1500 $code .= " }\n";
1501 }
1502
1503 if ($useExceptions) {
1504 if ($useExceptions) {
1505 $code .= " if (UNLIKELY(es.throwIfNeeded()))\n";
1506 $code .= " return;\n";
1507 }
1508
1509 if (ExtendedAttributeContains($attribute->extendedAttributes->{"Call With"}, "ScriptState")) {
1510 $code .= " if (state.hadException()) {\n";
1511 $code .= " throwError(state.exception(), info.GetIsolate( ));\n";
1512 $code .= " return;\n";
1513 $code .= " }\n";
1514 }
1515 }
1516
1517 $expression = "v";
1518 $expression .= ".release()" if (IsRefPtrType($returnType));
1519 } else {
1520 # Can inline the function call into the return statement to avoid overhe ad of using a Ref<> temporary
1521 $expression = $getterString;
1522 # 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).
1523 $expression = "static_pointer_cast<SVGAnimatedEnumeration>($expression)" if $returnType eq "SVGAnimatedEnumeration";
1524 }
1525
1526 if (ShouldKeepAttributeAlive($interface, $attribute, $returnType)) {
1527 my $arrayType = GetArrayType($returnType);
1528 if ($arrayType) {
1529 AddIncludeForType("V8$arrayType.h");
1530 $code .= " v8SetReturnValue(info, v8Array(${getterString}, info.G etIsolate()));\n";
1531 $code .= " return;\n";
1532 $code .= "}\n\n";
1533 $implementation{nameSpaceInternal}->add($code);
1534 return;
1535 }
1536
1537 AddIncludesForType($returnType);
1538 AddToImplIncludes("bindings/v8/V8HiddenPropertyName.h");
1539 # Check for a wrapper in the wrapper cache. If there is one, we know tha t a hidden reference has already
1540 # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference.
1541 my $nativeReturnType = GetNativeType($returnType);
1542 my $v8ReturnType = "V8" . $returnType;
1543 $code .= " $nativeReturnType result = ${getterString};\n";
1544 if ($forMainWorldSuffix) {
1545 $code .= " if (result.get() && DOMDataStore::setReturnValueFromWr apper${forMainWorldSuffix}<${v8ReturnType}>(info.GetReturnValue(), result.get()) )\n";
1546 } else {
1547 $code .= " if (result.get() && DOMDataStore::setReturnValueFromWr apper<${v8ReturnType}>(info.GetReturnValue(), result.get()))\n";
1548 }
1549 $code .= " return;\n";
1550 $code .= " v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Ho lder(), info.GetIsolate());\n";
1551 $code .= " if (!wrapper.IsEmpty()) {\n";
1552 $code .= " V8HiddenPropertyName::setNamedHiddenReference(info.Hol der(), \"${attrName}\", wrapper);\n";
1553 $code .= " v8SetReturnValue(info, wrapper);\n";
1554 $code .= " }\n";
1555 $code .= " return;\n";
1556 $code .= "}\n\n";
1557 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
1558 $implementation{nameSpaceInternal}->add($code);
1559 return;
1560 }
1561
1562 if ((IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") a nd IsSVGTypeNeedingTearOff($attrType)) {
1563 AddToImplIncludes("V8$attrType.h");
1564 my $svgNativeType = GetSVGTypeNeedingTearOff($attrType);
1565 # Convert from abstract SVGProperty to real type, so the right toJS() me thod can be invoked.
1566 if ($forMainWorldSuffix eq "ForMainWorld") {
1567 $code .= " v8SetReturnValueForMainWorld(info, static_cast<$svgNat iveType*>($expression), info.Holder());\n";
1568 } else {
1569 $code .= " v8SetReturnValueFast(info, static_cast<$svgNativeType* >($expression), imp);\n";
1570 }
1571 $code .= " return;\n";
1572 } elsif (IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$ /) {
1573 AddToImplIncludes("V8$attrType.h");
1574 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h");
1575 my $tearOffType = GetSVGTypeNeedingTearOff($attrType);
1576 my $wrappedValue;
1577 if (IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not def ined $attribute->extendedAttributes->{"Immutable"}) {
1578 my $getter = $expression;
1579 $getter =~ s/imp->//;
1580 $getter =~ s/\(\)//;
1581
1582 my $updateMethod = "&${implClassName}::update" . FirstLetterToUpperC ase($getter);
1583
1584 my $selfIsTearOffType = IsSVGTypeNeedingTearOff($interfaceName);
1585 if ($selfIsTearOffType) {
1586 AddToImplIncludes("core/svg/properties/SVGMatrixTearOff.h");
1587 # FIXME: Don't create a new one everytime we access the matrix p roperty. This means, e.g, === won't work.
1588 $wrappedValue = "WTF::getPtr(SVGMatrixTearOff::create(wrapper, $ expression))";
1589 } else {
1590 AddToImplIncludes("core/svg/properties/SVGStaticPropertyTearOff. h");
1591 $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$ implClassName, /;
1592
1593 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expres sion, $updateMethod))";
1594 }
1595 } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) {
1596 $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expres sion))";
1597 } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) {
1598 $wrappedValue = "WTF::getPtr($expression)";
1599 } else {
1600 $wrappedValue = "WTF::getPtr(${tearOffType}::create($expression) )";
1601 }
1602 if ($forMainWorldSuffix eq "ForMainWorld") {
1603 $code .= " v8SetReturnValueForMainWorld(info, $wrappedValue, info .Holder());\n";
1604 } else {
1605 $code .= " v8SetReturnValueFast(info, $wrappedValue, imp);\n";
1606 }
1607 $code .= " return;\n";
1608 } elsif ($attrCached) {
1609 if ($attribute->type eq "SerializedScriptValue") {
1610 $code .= " RefPtr<SerializedScriptValue> serialized = $getterStri ng;\n";
1611 $code .= " value = serialized ? serialized->deserialize() : v8::H andle<v8::Value>(v8::Null(info.GetIsolate()));\n";
1612 } else {
1613 $code .= " value = $getterString.v8Value();\n";
1614 }
1615 $code .= <<END;
1616 info.Holder()->SetHiddenValue(propertyName, value);
1617 v8SetReturnValue(info, value);
1618 return;
1619 END
1620 } elsif ($attribute->type eq "EventHandler") {
1621 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h");
1622 my $getterFunc = ToMethodName($attribute->name);
1623 # FIXME: Pass the main world ID for main-world-only getters.
1624 $code .= " EventListener* listener = imp->${getterFunc}(isolatedWorld ForIsolate(info.GetIsolate()));\n";
1625 $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";
1626 $code .= " return;\n";
1627 } else {
1628 my $nativeValue = NativeToJSValue($attribute->type, $attribute->extended Attributes, $expression, " ", "", "info.Holder()", "info.GetIsolate()", "info ", "imp", $forMainWorldSuffix, "return");
1629 $code .= "${nativeValue}\n";
1630 $code .= " return;\n";
1631 }
1632
1633 $code .= "}\n\n"; # end of getter
1634 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
1635 $implementation{nameSpaceInternal}->add($code);
1636 }
1637
1638 sub ShouldKeepAttributeAlive
1639 {
1640 my ($interface, $attribute, $returnType) = @_;
1641 my $attrName = $attribute->name;
1642
1643 return 1 if $attribute->extendedAttributes->{"KeepAttributeAliveForGC"};
1644
1645 # Basically, for readonly or replaceable attributes, we have to guarantee
1646 # that JS wrappers don't get garbage-collected prematually when their
1647 # lifetime is strongly tied to their owner.
1648 return 0 if !IsWrapperType($returnType);
1649 return 0 if !IsReadonly($attribute) && !$attribute->extendedAttributes->{"Re placeable"};
1650
1651 # However, there are a couple of exceptions.
1652
1653 # Node lifetime is managed by object grouping.
1654 return 0 if InheritsInterface($interface, "Node");
1655 return 0 if IsDOMNodeType($returnType);
1656
1657 # To avoid adding a reference to itself.
1658 # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove this hack
1659 # depending on the attribute name.
1660 return 0 if $attrName eq "self";
1661
1662 # FIXME: Remove these hard-coded hacks.
1663 return 0 if $returnType eq "EventTarget";
1664 return 0 if $returnType eq "SerializedScriptValue";
1665 return 0 if $returnType eq "Window";
1666 return 0 if $returnType =~ /SVG/;
1667 return 0 if $returnType =~ /HTML/;
1668
1669 return 1;
1670 }
1671
1672 sub GenerateReplaceableAttributeSetterCallback
1673 {
1674 my $interface = shift;
1675 my $implClassName = GetImplName($interface);
1676
1677 my $code = "";
1678 $code .= "static void ${implClassName}ReplaceableAttributeSetterCallback(v8: :Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackI nfo<void>& info)\n";
1679 $code .= "{\n";
1680 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"Measur eAs"});
1681 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"D eprecateAs"});
1682 $code .= GenerateCustomElementInvocationScopeIfNeeded($interface->extendedAt tributes);
1683 if (HasActivityLogging("", $interface->extendedAttributes, "Setter")) {
1684 die "IDL error: ActivityLog attribute cannot exist on a ReplacableAttri buteSetterCallback";
1685 }
1686 $code .= " ${implClassName}V8Internal::${implClassName}ReplaceableAttribu teSetter(name, value, info);\n";
1687 $code .= "}\n\n";
1688 $implementation{nameSpaceInternal}->add($code);
1689 }
1690
1691 sub GenerateReplaceableAttributeSetter
1692 {
1693 my $interface = shift;
1694
1695 my $implClassName = GetImplName($interface);
1696 my $v8ClassName = GetV8ClassName($interface);
1697
1698 my $code = "";
1699 $code .= <<END;
1700 static void ${implClassName}ReplaceableAttributeSetter(v8::Local<v8::String> nam e, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
1701 {
1702 END
1703 if ($interface->extendedAttributes->{"CheckSecurity"}) {
1704 AddToImplIncludes("bindings/v8/BindingSecurity.h");
1705 $code .= <<END;
1706 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1707 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame()))
1708 return;
1709 END
1710 }
1711
1712 $code .= <<END;
1713 info.This()->ForceSet(name, value);
1714 }
1715
1716 END
1717 $implementation{nameSpaceInternal}->add($code);
1718 }
1719
1720 sub GenerateCustomElementInvocationScopeIfNeeded
1721 {
1722 my $code = "";
1723 my $ext = shift;
1724 my $annotation = $ext->{"CustomElementCallbacks"} || "";
1725
1726 if ($annotation eq "None") {
1727 # Explicit CustomElementCallbacks=None overrides any other
1728 # heuristic.
1729 return $code;
1730 }
1731
1732 if ($annotation eq "Enable" or $ext->{"Reflect"}) {
1733 AddToImplIncludes("core/dom/CustomElementCallbackDispatcher.h");
1734 $code .= <<END;
1735 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
1736 END
1737 }
1738 return $code;
1739 }
1740
1741 sub GenerateNormalAttributeSetterCallback
1742 {
1743 my $attribute = shift;
1744 my $interface = shift;
1745 my $forMainWorldSuffix = shift;
1746
1747 my $implClassName = GetImplName($interface);
1748 my $v8ClassName = GetV8ClassName($interface);
1749 my $attrExt = $attribute->extendedAttributes;
1750 my $attrName = $attribute->name;
1751
1752 my $conditionalString = GenerateConditionalString($attribute);
1753 my $code = "";
1754 $code .= "#if ${conditionalString}\n\n" if $conditionalString;
1755
1756 $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSuffix }(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCall backInfo<void>& info)\n";
1757 $code .= "{\n";
1758 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMSetter\");\n";
1759 $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"});
1760 $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"});
1761 if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Setter")) {
1762 $code .= GenerateActivityLogging("Setter", $interface, "${attrName}");
1763 }
1764 $code .= GenerateCustomElementInvocationScopeIfNeeded($attrExt);
1765 if (HasCustomSetter($attrExt)) {
1766 $code .= " ${v8ClassName}::${attrName}AttributeSetterCustom(name, val ue, info);\n";
1767 } else {
1768 $code .= " ${implClassName}V8Internal::${attrName}AttributeSetter${fo rMainWorldSuffix}(name, value, info);\n";
1769 }
1770 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
1771 $code .= "}\n\n";
1772 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
1773 $implementation{nameSpaceInternal}->add($code);
1774 }
1775
1776 sub GenerateNormalAttributeSetter
1777 {
1778 my $attribute = shift;
1779 my $interface = shift;
1780 my $forMainWorldSuffix = shift;
1781
1782 my $interfaceName = $interface->name;
1783 my $implClassName = GetImplName($interface);
1784 my $v8ClassName = GetV8ClassName($interface);
1785 my $attrName = $attribute->name;
1786 my $attrExt = $attribute->extendedAttributes;
1787 my $attrType = $attribute->type;
1788 my $attrCached = GetCachedAttribute($attribute);
1789
1790 if (HasCustomSetter($attrExt)) {
1791 return;
1792 }
1793
1794 my $conditionalString = GenerateConditionalString($attribute);
1795 my $code = "";
1796 $code .= "#if ${conditionalString}\n\n" if $conditionalString;
1797 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8::Lo cal<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo <void>& info)\n";
1798 $code .= "{\n";
1799
1800 # If the "StrictTypeChecking" extended attribute is present, and the attribu te's type is an
1801 # interface type, then if the incoming value does not implement that interfa ce, a TypeError is
1802 # thrown rather than silently passing NULL to the C++ code.
1803 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to both
1804 # strings and numbers, so do not throw TypeError if the attribute is of thes e types.
1805 if ($attribute->extendedAttributes->{"StrictTypeChecking"}) {
1806 my $argType = $attribute->type;
1807 if (IsWrapperType($argType)) {
1808 $code .= " if (!isUndefinedOrNull(value) && !V8${argType}::HasIns tance(value, info.GetIsolate(), worldType(info.GetIsolate()))) {\n";
1809 $code .= " throwTypeError(info.GetIsolate());\n";
1810 $code .= " return;\n";
1811 $code .= " }\n";
1812 }
1813 }
1814
1815 my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName);
1816 if ($svgNativeType) {
1817 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceNam e);
1818 if ($svgWrappedNativeType =~ /List$/) {
1819 $code .= <<END;
1820 $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder());
1821 END
1822 } else {
1823 AddToImplIncludes("bindings/v8/ExceptionState.h");
1824 $code .= " $svgNativeType* wrapper = ${v8ClassName}::toNative(inf o.Holder());\n";
1825 $code .= " if (wrapper->isReadOnly()) {\n";
1826 $code .= " setDOMException(NoModificationAllowedError, info.G etIsolate());\n";
1827 $code .= " return;\n";
1828 $code .= " }\n";
1829 $code .= " $svgWrappedNativeType& impInstance = wrapper->property Reference();\n";
1830 $code .= " $svgWrappedNativeType* imp = &impInstance;\n";
1831 }
1832 } elsif ($attrExt->{"OnProto"}) {
1833 $code .= <<END;
1834 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1835 END
1836 } else {
1837 my $reflect = $attribute->extendedAttributes->{"Reflect"};
1838 if ($reflect && InheritsInterface($interface, "Node") && $attrType eq "D OMString") {
1839 # Generate super-compact call for regular attribute setter:
1840 my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attr Name : $reflect;
1841 my $namespace = NamespaceForAttributeName($interfaceName, $contentAt tributeName);
1842 AddToImplIncludes("${namespace}.h");
1843 $code .= " Element* imp = V8Element::toNative(info.Holder());\n";
1844 $code .= " V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource< WithNullCheck>, stringResource, value);\n";
1845 # Attr (not Attribute) used in content attributes
1846 $code .= " imp->setAttribute(${namespace}::${contentAttributeName }Attr, stringResource);\n";
1847 $code .= "}\n\n";
1848 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
1849 $implementation{nameSpaceInternal}->add($code);
1850 return;
1851 # Skip the rest of the function!
1852 }
1853
1854 if (!$attribute->isStatic) {
1855 $code .= <<END;
1856 ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder());
1857 END
1858 }
1859 }
1860
1861 my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttribu tes, "parameter");
1862 if ($attribute->type eq "EventHandler") {
1863 if ($interface->name eq "Window") {
1864 $code .= " if (!imp->document())\n";
1865 $code .= " return;\n";
1866 }
1867 } else {
1868 $code .= JSValueToNativeStatement($attribute->type, $attribute->extended Attributes, "value", "v", " ", "info.GetIsolate()");
1869 }
1870
1871 if (IsEnumType($attrType)) {
1872 # setter ignores invalid enumeration values
1873 my @enumValues = ValidEnumValues($attrType);
1874 my @validEqualities = ();
1875 foreach my $enumValue (@enumValues) {
1876 push(@validEqualities, "string == \"$enumValue\"");
1877 }
1878 my $enumValidationExpression = join(" || ", @validEqualities);
1879 $code .= <<END;
1880 String string = v;
1881 if (!($enumValidationExpression))
1882 return;
1883 END
1884 }
1885
1886 my $expression = "v";
1887 my $returnType = $attribute->type;
1888 if (IsRefPtrType($returnType) && !GetArrayType($returnType)) {
1889 $expression = "WTF::getPtr(" . $expression . ")";
1890 }
1891
1892 $code .= GenerateCustomElementInvocationScopeIfNeeded($attribute->extendedAt tributes);
1893
1894 my $useExceptions = 1 if $attribute->extendedAttributes->{"SetterRaisesExcep tion"} || $attribute->extendedAttributes->{"RaisesException"};
1895
1896 if ($useExceptions) {
1897 AddToImplIncludes("bindings/v8/ExceptionState.h");
1898 $code .= " ExceptionState es(info.GetIsolate());\n";
1899 }
1900
1901 if ($attribute->type eq "EventHandler") {
1902 my $implSetterFunctionName = FirstLetterToUpperCase($attrName);
1903 AddToImplIncludes("bindings/v8/V8AbstractEventListener.h");
1904 # Non callable input should be treated as null
1905 $code .= " if (!value->IsNull() && !value->IsFunction())\n";
1906 $code .= " value = v8::Null(info.GetIsolate());\n";
1907 if (!InheritsInterface($interface, "Node")) {
1908 my $attrImplName = GetImplName($attribute);
1909 $code .= " transferHiddenDependency(info.Holder(), imp->${attrImp lName}(isolatedWorldForIsolate(info.GetIsolate())), value, ${v8ClassName}::event ListenerCacheIndex, info.GetIsolate());\n";
1910 }
1911 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
1912 if (($interfaceName eq "Window" or $interfaceName eq "WorkerGlobalScope" ) and $attribute->name eq "onerror") {
1913 AddToImplIncludes("bindings/v8/V8ErrorHandler.h");
1914 $code .= " imp->set$implSetterFunctionName(V8EventListenerList::f indOrCreateWrapper<V8ErrorHandler>(value, true), isolatedWorldForIsolate(info.Ge tIsolate()));\n";
1915 } else {
1916 $code .= " imp->set$implSetterFunctionName(V8EventListenerList::g etEventListener(value, true, ListenerFindOrCreate), isolatedWorldForIsolate(info .GetIsolate()));\n";
1917 }
1918 } else {
1919 my ($functionName, @arguments) = SetterExpression($interfaceName, $attri bute);
1920 push(@arguments, $expression);
1921 push(@arguments, "es") if $useExceptions;
1922 if ($attribute->extendedAttributes->{"ImplementedBy"}) {
1923 my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy" };
1924 my $implementedByImplName = GetImplNameFromImplementedBy($implemente dBy);
1925 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implement edByImplName));
1926 unshift(@arguments, "imp") if !$attribute->isStatic;
1927 $functionName = "${implementedByImplName}::${functionName}";
1928 } elsif ($attribute->isStatic) {
1929 $functionName = "${implClassName}::${functionName}";
1930 } else {
1931 $functionName = "imp->${functionName}";
1932 }
1933 my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{ "SetterCallWith"} || $attribute->extendedAttributes->{"CallWith"}, " ", 1);
1934 $code .= $subCode;
1935 unshift(@arguments, @$arg);
1936 $code .= " ${functionName}(" . join(", ", @arguments) . ");\n";
1937 }
1938
1939 if ($useExceptions) {
1940 $code .= " es.throwIfNeeded();\n";
1941 }
1942
1943 if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) {
1944 $code .= " if (state.hadException())\n";
1945 $code .= " throwError(state.exception(), info.GetIsolate());\n";
1946 }
1947
1948 if ($svgNativeType) {
1949 if ($useExceptions) {
1950 $code .= " if (!es.hadException())\n";
1951 $code .= " wrapper->commitChange();\n";
1952 } else {
1953 $code .= " wrapper->commitChange();\n";
1954 }
1955 }
1956
1957 if ($attrCached) {
1958 $code .= <<END;
1959 info.Holder()->DeleteHiddenValue(v8::String::NewSymbol("${attrName}")); // I nvalidate the cached value.
1960 END
1961 }
1962
1963 $code .= " return;\n";
1964 $code .= "}\n\n"; # end of setter
1965 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
1966 $implementation{nameSpaceInternal}->add($code);
1967 }
1968
1969 sub GenerateParametersCheckExpression
1970 {
1971 my $numParameters = shift;
1972 my $function = shift;
1973
1974 my @andExpression = ();
1975 push(@andExpression, "args.Length() == $numParameters");
1976 my $parameterIndex = 0;
1977 foreach my $parameter (@{$function->parameters}) {
1978 last if $parameterIndex >= $numParameters;
1979 my $value = "args[$parameterIndex]";
1980 my $type = $parameter->type;
1981
1982 # Only DOMString or wrapper types are checked.
1983 # For DOMString with StrictTypeChecking only Null, Undefined and Object
1984 # are accepted for compatibility. Otherwise, no restrictions are made to
1985 # match the non-overloaded behavior.
1986 # FIXME: Implement WebIDL overload resolution algorithm.
1987 if ($type eq "DOMString") {
1988 if ($parameter->extendedAttributes->{"StrictTypeChecking"}) {
1989 push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefin ed() || ${value}->IsString() || ${value}->IsObject())");
1990 }
1991 } elsif (IsCallbackInterface($parameter->type)) {
1992 # For Callbacks only checks if the value is null or object.
1993 push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction()) ");
1994 } elsif (GetArrayOrSequenceType($type)) {
1995 if ($parameter->isNullable) {
1996 push(@andExpression, "(${value}->IsNull() || ${value}->IsArray() )");
1997 } else {
1998 push(@andExpression, "(${value}->IsArray())");
1999 }
2000 } elsif (IsWrapperType($type)) {
2001 if ($parameter->isNullable) {
2002 push(@andExpression, "(${value}->IsNull() || V8${type}::HasInsta nce($value, args.GetIsolate(), worldType(args.GetIsolate())))");
2003 } else {
2004 push(@andExpression, "(V8${type}::HasInstance($value, args.GetIs olate(), worldType(args.GetIsolate())))");
2005 }
2006 }
2007
2008 $parameterIndex++;
2009 }
2010 my $res = join(" && ", @andExpression);
2011 $res = "($res)" if @andExpression > 1;
2012 return $res;
2013 }
2014
2015 # As per Web IDL specification, the length of a function Object is
2016 # its number of mandatory parameters.
2017 sub GetFunctionLength
2018 {
2019 my $function = shift;
2020
2021 my $numMandatoryParams = 0;
2022 foreach my $parameter (@{$function->parameters}) {
2023 # Abort as soon as we find the first optional parameter as no mandatory
2024 # parameter can follow an optional one.
2025 last if $parameter->isOptional;
2026 $numMandatoryParams++;
2027 }
2028 return $numMandatoryParams;
2029 }
2030
2031 sub GenerateFunctionParametersCheck
2032 {
2033 my $function = shift;
2034
2035 my @orExpression = ();
2036 my $numParameters = 0;
2037 my $hasVariadic = 0;
2038 my $numMandatoryParams = @{$function->parameters};
2039 foreach my $parameter (@{$function->parameters}) {
2040 if ($parameter->isOptional) {
2041 push(@orExpression, GenerateParametersCheckExpression($numParameters , $function));
2042 $numMandatoryParams--;
2043 }
2044 if ($parameter->isVariadic) {
2045 $hasVariadic = 1;
2046 last;
2047 }
2048 $numParameters++;
2049 }
2050 if (!$hasVariadic) {
2051 push(@orExpression, GenerateParametersCheckExpression($numParameters, $f unction));
2052 }
2053 return ($numMandatoryParams, join(" || ", @orExpression));
2054 }
2055
2056 sub GenerateOverloadedFunction
2057 {
2058 my $function = shift;
2059 my $interface = shift;
2060 my $forMainWorldSuffix = shift;
2061
2062 # Generate code for choosing the correct overload to call. Overloads are
2063 # chosen based on the total number of arguments passed and the type of
2064 # values passed in non-primitive argument slots. When more than a single
2065 # overload is applicable, precedence is given according to the order of
2066 # declaration in the IDL.
2067
2068 my $name = $function->name;
2069
2070 my $conditionalString = GenerateConditionalString($function);
2071 my $leastNumMandatoryParams = 255;
2072 my $code = "";
2073 $code .= "#if ${conditionalString}\n\n" if $conditionalString;
2074 $code .= <<END;
2075 static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8 ::Value>& args)
2076 {
2077 END
2078 $code .= GenerateFeatureObservation($function->extendedAttributes->{"Measure As"});
2079 $code .= GenerateDeprecationNotification($function->extendedAttributes->{"De precateAs"});
2080
2081 foreach my $overload (@{$function->{overloads}}) {
2082 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersC heck($overload);
2083 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
2084 $code .= " if ($parametersCheck) {\n";
2085 my $overloadedIndexString = $overload->{overloadIndex};
2086 $code .= " ${name}${overloadedIndexString}Method${forMainWorldSuf fix}(args);\n";
2087 $code .= " return;\n";
2088 $code .= " }\n";
2089 }
2090 if ($leastNumMandatoryParams >= 1) {
2091 $code .= " if (UNLIKELY(args.Length() < $leastNumMandatoryParams)) {\ n";
2092 $code .= " throwNotEnoughArgumentsError(args.GetIsolate());\n";
2093 $code .= " return;\n";
2094 $code .= " }\n";
2095 }
2096 $code .= <<END;
2097 throwTypeError(args.GetIsolate());
2098 END
2099 $code .= "}\n\n";
2100 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
2101 $implementation{nameSpaceInternal}->add($code);
2102 }
2103
2104 sub GenerateFunctionCallback
2105 {
2106 my $function = shift;
2107 my $interface = shift;
2108 my $forMainWorldSuffix = shift;
2109
2110 my $implClassName = GetImplName($interface);
2111 my $v8ClassName = GetV8ClassName($interface);
2112 my $name = $function->name;
2113
2114 if ($name eq "") {
2115 return;
2116 }
2117
2118 my $conditionalString = GenerateConditionalString($function);
2119 my $code = "";
2120 $code .= "#if ${conditionalString}\n\n" if $conditionalString;
2121 $code .= <<END;
2122 static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbac kInfo<v8::Value>& args)
2123 {
2124 END
2125 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n";
2126 $code .= GenerateFeatureObservation($function->extendedAttributes->{"Measure As"});
2127 $code .= GenerateDeprecationNotification($function->extendedAttributes->{"De precateAs"});
2128 if (HasActivityLogging($forMainWorldSuffix, $function->extendedAttributes, " Access")) {
2129 $code .= GenerateActivityLogging("Method", $interface, "${name}");
2130 }
2131 if (HasCustomMethod($function->extendedAttributes)) {
2132 $code .= " ${v8ClassName}::${name}MethodCustom(args);\n";
2133 } else {
2134 $code .= " ${implClassName}V8Internal::${name}Method${forMainWorldSuf fix}(args);\n";
2135 }
2136 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
2137 $code .= "}\n\n";
2138 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
2139 $implementation{nameSpaceInternal}->add($code);
2140 }
2141
2142 sub GenerateFunction
2143 {
2144 my $function = shift;
2145 my $interface = shift;
2146 my $forMainWorldSuffix = shift;
2147
2148 my $interfaceName = $interface->name;
2149 my $implClassName = GetImplName($interface);
2150 my $v8ClassName = GetV8ClassName($interface);
2151 my $name = $function->name;
2152 my $implName = GetImplName($function);
2153 my $funcExt = $function->extendedAttributes;
2154
2155 if (HasCustomMethod($funcExt) || $name eq "") {
2156 return;
2157 }
2158
2159 if (@{$function->{overloads}} > 1) {
2160 # Append a number to an overloaded method's name to make it unique:
2161 $name = $name . $function->{overloadIndex};
2162 }
2163
2164 my $conditionalString = GenerateConditionalString($function);
2165 my $code = "";
2166 $code .= "#if ${conditionalString}\n\n" if $conditionalString;
2167 $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionC allbackInfo<v8::Value>& args)\n";
2168 $code .= "{\n";
2169
2170 if ($name eq "addEventListener" || $name eq "removeEventListener") {
2171 my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only";
2172 my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()";
2173 my $hiddenDependencyAction = ($name eq "addEventListener") ? "create" : "remove";
2174
2175 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2176 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
2177 AddToImplIncludes("core/page/DOMWindow.h");
2178 $code .= <<END;
2179 EventTarget* impl = ${v8ClassName}::toNative(args.Holder());
2180 if (DOMWindow* window = impl->toDOMWindow()) {
2181 if (!BindingSecurity::shouldAllowAccessToFrame(window->frame()))
2182 return;
2183
2184 if (!window->document())
2185 return;
2186 }
2187
2188 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[ 1], false, ListenerFind${lookupType});
2189 if (listener) {
2190 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, st ringResource, args[0]);
2191 impl->${implName}(stringResource, listener${passRefPtrHandling}, args[2] ->BooleanValue());
2192 if (!impl->toNode())
2193 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], ${ v8ClassName}::eventListenerCacheIndex, args.GetIsolate());
2194 }
2195 }
2196
2197 END
2198 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
2199 $implementation{nameSpaceInternal}->add($code);
2200 return;
2201 }
2202
2203 $code .= GenerateArgumentsCountCheck($function, $interface);
2204
2205 if ($name eq "set" and IsConstructorTemplate($interface, "TypedArray")) {
2206 AddToImplIncludes("bindings/v8/custom/V8ArrayBufferViewCustom.h");
2207 $code .= <<END;
2208 setWebGLArrayHelper<$implClassName, ${v8ClassName}>(args);
2209 }
2210
2211 END
2212 $implementation{nameSpaceInternal}->add($code);
2213 return;
2214 }
2215
2216 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty Types($interfaceName);
2217
2218 if ($svgNativeType) {
2219 my $nativeClassName = GetNativeType($interfaceName);
2220 if ($interfaceName =~ /List$/) {
2221 $code .= " $nativeClassName imp = ${v8ClassName}::toNative(args.H older());\n";
2222 } else {
2223 AddToImplIncludes("bindings/v8/ExceptionState.h");
2224 AddToImplIncludes("core/dom/ExceptionCode.h");
2225 $code .= " $nativeClassName wrapper = ${v8ClassName}::toNative(ar gs.Holder());\n";
2226 $code .= " if (wrapper->isReadOnly()) {\n";
2227 $code .= " setDOMException(NoModificationAllowedError, args.G etIsolate());\n";
2228 $code .= " return;\n";
2229 $code .= " }\n";
2230 my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfac eName);
2231 $code .= " $svgWrappedNativeType& impInstance = wrapper->property Reference();\n";
2232 $code .= " $svgWrappedNativeType* imp = &impInstance;\n";
2233 }
2234 } elsif (!$function->isStatic) {
2235 $code .= <<END;
2236 ${implClassName}* imp = ${v8ClassName}::toNative(args.Holder());
2237 END
2238 }
2239
2240 $code .= GenerateCustomElementInvocationScopeIfNeeded($funcExt);
2241
2242 # Check domain security if needed
2243 if ($interface->extendedAttributes->{"CheckSecurity"} && !$function->extende dAttributes->{"DoNotCheckSecurity"}) {
2244 # We have not find real use cases yet.
2245 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2246 $code .= <<END;
2247 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame()))
2248 return;
2249 END
2250 }
2251
2252 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
2253 if ($raisesExceptions) {
2254 AddToImplIncludes("bindings/v8/ExceptionState.h");
2255 $code .= " ExceptionState es(args.GetIsolate());\n";
2256 }
2257
2258 if ($function->extendedAttributes->{"CheckSecurityForNode"}) {
2259 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2260 $code .= " if (!BindingSecurity::shouldAllowAccessToNode(imp->" . Get ImplName($function) . "(es))) {\n";
2261 $code .= " v8SetReturnValueNull(args);\n";
2262 $code .= " return;\n";
2263 $code .= " }\n";
2264 END
2265 }
2266
2267 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, $forMainWorldSuffix);
2268 $code .= $parameterCheckString;
2269
2270 # Build the function call string.
2271 $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interfa ce, $forMainWorldSuffix, %replacements);
2272 $code .= "}\n\n";
2273 $code .= "#endif // ${conditionalString}\n\n" if $conditionalString;
2274 $implementation{nameSpaceInternal}->add($code);
2275 }
2276
2277 sub GenerateCallWith
2278 {
2279 my $callWith = shift;
2280 return ([], "") unless $callWith;
2281 my $indent = shift;
2282 my $returnVoid = shift;
2283 my $function = shift;
2284 my $code = "";
2285
2286 my @callWithArgs;
2287 if (ExtendedAttributeContains($callWith, "ScriptState")) {
2288 $code .= $indent . "ScriptState* currentState = ScriptState::current();\ n";
2289 $code .= $indent . "if (!currentState)\n";
2290 $code .= $indent . " return" . ($returnVoid ? "" : " v8Undefined()") . ";\n";
2291 $code .= $indent . "ScriptState& state = *currentState;\n";
2292 push(@callWithArgs, "&state");
2293 }
2294 if (ExtendedAttributeContains($callWith, "ScriptExecutionContext")) {
2295 $code .= $indent . "ScriptExecutionContext* scriptContext = getScriptExe cutionContext();\n";
2296 push(@callWithArgs, "scriptContext");
2297 }
2298 if ($function and ExtendedAttributeContains($callWith, "ScriptArguments")) {
2299 $code .= $indent . "RefPtr<ScriptArguments> scriptArguments(createScript Arguments(args, " . @{$function->parameters} . "));\n";
2300 push(@callWithArgs, "scriptArguments.release()");
2301 AddToImplIncludes("bindings/v8/ScriptCallStackFactory.h");
2302 AddToImplIncludes("core/inspector/ScriptArguments.h");
2303 }
2304 if (ExtendedAttributeContains($callWith, "ActiveWindow")) {
2305 push(@callWithArgs, "activeDOMWindow()");
2306 }
2307 if (ExtendedAttributeContains($callWith, "FirstWindow")) {
2308 push(@callWithArgs, "firstDOMWindow()");
2309 }
2310 return ([@callWithArgs], $code);
2311 }
2312
2313 sub GenerateArgumentsCountCheck
2314 {
2315 my $function = shift;
2316 my $interface = shift;
2317
2318 my $numMandatoryParams = 0;
2319 my $allowNonOptional = 1;
2320 foreach my $param (@{$function->parameters}) {
2321 if ($param->isOptional or $param->isVariadic) {
2322 $allowNonOptional = 0;
2323 } else {
2324 die "An argument must not be declared to be optional unless all subs equent arguments to the operation are also optional." if !$allowNonOptional;
2325 $numMandatoryParams++;
2326 }
2327 }
2328
2329 my $argumentsCountCheckString = "";
2330 if ($numMandatoryParams >= 1) {
2331 $argumentsCountCheckString .= " if (UNLIKELY(args.Length() < $numMand atoryParams)) {\n";
2332 $argumentsCountCheckString .= " throwNotEnoughArgumentsError(args .GetIsolate());\n";
2333 $argumentsCountCheckString .= " return;\n";
2334 $argumentsCountCheckString .= " }\n";
2335 }
2336 return $argumentsCountCheckString;
2337 }
2338
2339 sub GenerateParametersCheck
2340 {
2341 my $function = shift;
2342 my $interface = shift;
2343 my $forMainWorldSuffix = shift;
2344 my $style = shift || "new";
2345
2346 my $parameterCheckString = "";
2347 my $paramIndex = 0;
2348 my %replacements = ();
2349
2350 foreach my $parameter (@{$function->parameters}) {
2351 my $nativeType = GetNativeType($parameter->type, $parameter->extendedAtt ributes, "parameter");
2352
2353 # Optional arguments without [Default=...] should generate an early call with fewer arguments.
2354 # Optional arguments with [Optional=...] should not generate the early c all.
2355 # Optional Dictionary arguments always considered to have default of emp ty dictionary.
2356 if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default "} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) {
2357 $parameterCheckString .= " if (UNLIKELY(args.Length() <= $paramIn dex))";
2358 my $functionCall = GenerateFunctionCallString($function, $paramIndex , " " x 2, $interface, $forMainWorldSuffix, %replacements);
2359 my $multiLine = ($functionCall =~ tr/\n//) > 1;
2360 $parameterCheckString .= $multiLine ? " {\n" : "\n";
2361 $parameterCheckString .= $functionCall;
2362 $parameterCheckString .= $multiLine ? " }\n" : "\n";
2363 }
2364
2365 my $parameterName = $parameter->name;
2366 AddToImplIncludes("bindings/v8/ExceptionState.h");
2367 if (IsCallbackInterface($parameter->type)) {
2368 my $v8ClassName = "V8" . $parameter->type;
2369 AddToImplIncludes("$v8ClassName.h");
2370 if ($parameter->isOptional) {
2371 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $ parameterName;\n";
2372 $parameterCheckString .= " if (args.Length() > $paramIndex && !args[$paramIndex]->IsNull() && !args[$paramIndex]->IsUndefined()) {\n";
2373 $parameterCheckString .= " if (!args[$paramIndex]->IsFunc tion()) {\n";
2374 $parameterCheckString .= " throwTypeError(args.GetIso late());\n";
2375 $parameterCheckString .= " return;\n";
2376 $parameterCheckString .= " }\n";
2377 $parameterCheckString .= " $parameterName = ${v8ClassName }::create(args[$paramIndex], getScriptExecutionContext());\n";
2378 $parameterCheckString .= " }\n";
2379 } else {
2380 $parameterCheckString .= " if (args.Length() <= $paramIndex | | ";
2381 if ($parameter->isNullable) {
2382 $parameterCheckString .= "!(args[$paramIndex]->IsFunction() || args[$paramIndex]->IsNull())";
2383 } else {
2384 $parameterCheckString .= "!args[$paramIndex]->IsFunction()";
2385 }
2386 $parameterCheckString .= ") {\n";
2387 $parameterCheckString .= " throwTypeError(args.GetIsolate ());\n";
2388 $parameterCheckString .= " return;\n";
2389 $parameterCheckString .= " }\n";
2390 $parameterCheckString .= " RefPtr<" . $parameter->type . "> $ parameterName = ";
2391 $parameterCheckString .= "args[$paramIndex]->IsNull() ? 0 : " if $parameter->isNullable;
2392 $parameterCheckString .= "${v8ClassName}::create(args[$paramInde x], getScriptExecutionContext());\n";
2393 }
2394 } elsif ($parameter->extendedAttributes->{"Clamp"}) {
2395 my $nativeValue = "${parameterName}NativeValue";
2396 my $paramType = $parameter->type;
2397 $parameterCheckString .= " $paramType $parameterName = 0;\n";
2398 $parameterCheckString .= " V8TRYCATCH_VOID(double, $nativeVal ue, args[$paramIndex]->NumberValue());\n";
2399 $parameterCheckString .= " if (!std::isnan($nativeValue))\n";
2400 $parameterCheckString .= " $parameterName = clampTo<$para mType>($nativeValue);\n";
2401 } elsif ($parameter->type eq "SerializedScriptValue") {
2402 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
2403 $parameterCheckString .= " bool ${parameterName}DidThrow = false; \n";
2404 $parameterCheckString .= " $nativeType $parameterName = Serialize dScriptValue::create(args[$paramIndex], 0, 0, ${parameterName}DidThrow, args.Get Isolate());\n";
2405 $parameterCheckString .= " if (${parameterName}DidThrow)\n";
2406 $parameterCheckString .= " return;\n";
2407 } elsif ($parameter->isVariadic) {
2408 my $nativeElementType = GetNativeType($parameter->type);
2409 if ($nativeElementType =~ />$/) {
2410 $nativeElementType .= " ";
2411 }
2412
2413 my $argType = $parameter->type;
2414 if (IsWrapperType($argType)) {
2415 $parameterCheckString .= " Vector<$nativeElementType> $parame terName;\n";
2416 $parameterCheckString .= " for (int i = $paramIndex; i < args .Length(); ++i) {\n";
2417 $parameterCheckString .= " if (!V8${argType}::HasInstance (args[i], args.GetIsolate(), worldType(args.GetIsolate()))) {\n";
2418 $parameterCheckString .= " throwTypeError(args.GetIso late());\n";
2419 $parameterCheckString .= " return;\n";
2420 $parameterCheckString .= " }\n";
2421 $parameterCheckString .= " $parameterName.append(V8${argT ype}::toNative(v8::Handle<v8::Object>::Cast(args[i])));\n";
2422 $parameterCheckString .= " }\n";
2423 } else {
2424 $parameterCheckString .= " V8TRYCATCH_VOID(Vector<$nativeElem entType>, $parameterName, toNativeArguments<$nativeElementType>(args, $paramInde x));\n";
2425 }
2426 } elsif ($nativeType =~ /^V8StringResource/) {
2427 my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : "";
2428 my $jsValue = $parameter->isOptional && $default eq "NullString" ? " argumentOrNull(args, $paramIndex)" : "args[$paramIndex]";
2429 $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $jsValue, $parameterName, " ", "args.GetIsola te()");
2430 if (IsEnumType($parameter->type)) {
2431 my @enumValues = ValidEnumValues($parameter->type);
2432 my @validEqualities = ();
2433 foreach my $enumValue (@enumValues) {
2434 push(@validEqualities, "string == \"$enumValue\"");
2435 }
2436 my $enumValidationExpression = join(" || ", @validEqualities);
2437 $parameterCheckString .= " String string = $parameterName;\n ";
2438 $parameterCheckString .= " if (!($enumValidationExpression)) {\n";
2439 $parameterCheckString .= " throwTypeError(args.GetIsolate ());\n";
2440 $parameterCheckString .= " return;\n";
2441 $parameterCheckString .= " }\n";
2442 }
2443 } else {
2444 # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an
2445 # interface type, then if the incoming value does not implement that interface, a TypeError
2446 # is thrown rather than silently passing NULL to the C++ code.
2447 # Per the Web IDL and ECMAScript specifications, incoming values can always be converted
2448 # to both strings and numbers, so do not throw TypeError if the argu ment is of these
2449 # types.
2450 if ($function->extendedAttributes->{"StrictTypeChecking"}) {
2451 my $argValue = "args[$paramIndex]";
2452 my $argType = $parameter->type;
2453 if (IsWrapperType($argType)) {
2454 $parameterCheckString .= " if (args.Length() > $paramInde x && !isUndefinedOrNull($argValue) && !V8${argType}::HasInstance($argValue, args .GetIsolate(), worldType(args.GetIsolate()))) {\n";
2455 $parameterCheckString .= " throwTypeError(args.GetIso late());\n";
2456 $parameterCheckString .= " return;\n";
2457 $parameterCheckString .= " }\n";
2458 }
2459 }
2460 my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : "";
2461 my $jsValue = $parameter->isOptional && $default eq "NullString" ? " argumentOrNull(args, $paramIndex)" : "args[$paramIndex]";
2462 $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $jsValue, $parameterName, " ", "args.GetIsola te()");
2463 if ($nativeType eq 'Dictionary' or $nativeType eq 'ScriptPromise') {
2464 $parameterCheckString .= " if (!$parameterName.isUndefinedOrN ull() && !$parameterName.isObject()) {\n";
2465 $parameterCheckString .= " throwTypeError(\"Not an object .\", args.GetIsolate());\n";
2466 $parameterCheckString .= " return;\n";
2467 $parameterCheckString .= " }\n";
2468 }
2469 }
2470
2471 $paramIndex++;
2472 }
2473 return ($parameterCheckString, $paramIndex, %replacements);
2474 }
2475
2476 sub GenerateOverloadedConstructorCallback
2477 {
2478 my $interface = shift;
2479 my $implClassName = GetImplName($interface);
2480
2481 my $code = "";
2482 $code .= <<END;
2483 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args)
2484 {
2485 END
2486 my $leastNumMandatoryParams = 255;
2487 foreach my $constructor (@{$interface->constructors}) {
2488 my $name = "constructor" . $constructor->overloadedIndex;
2489 my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersC heck($constructor);
2490 $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams);
2491 $code .= " if ($parametersCheck) {\n";
2492 $code .= " ${implClassName}V8Internal::${name}(args);\n";
2493 $code .= " return;\n";
2494 $code .= " }\n";
2495 }
2496 if ($leastNumMandatoryParams >= 1) {
2497 $code .= " if (UNLIKELY(args.Length() < $leastNumMandatoryParams)) {\ n";
2498 $code .= " throwNotEnoughArgumentsError(args.GetIsolate());\n";
2499 $code .= " return;\n";
2500 $code .= " }\n";
2501 }
2502 $code .= <<END;
2503 throwTypeError(args.GetIsolate());
2504 return;
2505 END
2506 $code .= "}\n\n";
2507 $implementation{nameSpaceInternal}->add($code);
2508 }
2509
2510 sub GenerateSingleConstructorCallback
2511 {
2512 my $interface = shift;
2513 my $function = shift;
2514
2515 my $implClassName = GetImplName($interface);
2516 my $v8ClassName = GetV8ClassName($interface);
2517 my $overloadedIndexString = "";
2518 if ($function->overloadedIndex > 0) {
2519 $overloadedIndexString .= $function->overloadedIndex;
2520 }
2521
2522 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
2523 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2524 $raisesExceptions = 1;
2525 }
2526
2527 my @beforeArgumentList;
2528 my @afterArgumentList;
2529 my $code = "";
2530 $code .= <<END;
2531 static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v 8::Value>& args)
2532 {
2533 END
2534
2535 if ($function->overloadedIndex == 0) {
2536 $code .= GenerateArgumentsCountCheck($function, $interface);
2537 }
2538
2539 if ($raisesExceptions) {
2540 AddToImplIncludes("bindings/v8/ExceptionState.h");
2541 $code .= " ExceptionState es(args.GetIsolate());\n";
2542 }
2543
2544 # FIXME: Currently [Constructor(...)] does not yet support optional argument s without [Default=...]
2545 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, "");
2546 $code .= $parameterCheckString;
2547
2548 if ($interface->extendedAttributes->{"ConstructorCallWith"}) {
2549 if ($interface->extendedAttributes->{"ConstructorCallWith"} eq "ScriptEx ecutionContext") {
2550 push(@beforeArgumentList, "context");
2551 $code .= "\n";
2552 $code .= " ScriptExecutionContext* context = getScriptExecutionCo ntext();";
2553 } elsif ($interface->extendedAttributes->{"ConstructorCallWith"} eq "Doc ument") {
2554 push(@beforeArgumentList, "document");
2555 $code .= "\n";
2556 $code .= " Document& document = *toDocument(getScriptExecutionCon text());";
2557 }
2558 }
2559
2560 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2561 push(@afterArgumentList, "es");
2562 }
2563
2564 my @argumentList;
2565 my $index = 0;
2566 foreach my $parameter (@{$function->parameters}) {
2567 last if $index eq $paramIndex;
2568 if ($replacements{$parameter->name}) {
2569 push(@argumentList, $replacements{$parameter->name});
2570 } else {
2571 push(@argumentList, $parameter->name);
2572 }
2573 $index++;
2574 }
2575
2576 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterAr gumentList);
2577 $code .= "\n";
2578 $code .= " RefPtr<${implClassName}> impl = ${implClassName}::create(${arg umentString});\n";
2579 $code .= " v8::Handle<v8::Object> wrapper = args.Holder();\n";
2580
2581 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2582 $code .= " if (es.throwIfNeeded())\n";
2583 $code .= " return;\n";
2584 }
2585
2586 $code .= <<END;
2587
2588 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${ v8ClassName}::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent) ;
2589 args.GetReturnValue().Set(wrapper);
2590 }
2591
2592 END
2593 $implementation{nameSpaceInternal}->add($code);
2594 }
2595
2596 # The Web IDL specification states that Interface objects for interfaces MUST ha ve a property named
2597 # "length" that returns the length of the shortest argument list of the entries in the effective
2598 # overload set for constructors. In other words, use the lowest number of mandat ory arguments among
2599 # all constructors.
2600 sub GetInterfaceLength
2601 {
2602 my $interface = shift;
2603
2604 my $leastConstructorLength = 0;
2605 if (IsConstructorTemplate($interface, "Event") || IsConstructorTemplate($int erface, "TypedArray")) {
2606 $leastConstructorLength = 1;
2607 } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->exte ndedAttributes->{"CustomConstructor"}) {
2608 my @constructors = @{$interface->constructors};
2609 my @customConstructors = @{$interface->customConstructors};
2610 $leastConstructorLength = 255;
2611 foreach my $constructor (@constructors, @customConstructors) {
2612 my $constructorLength = GetFunctionLength($constructor);
2613 $leastConstructorLength = $constructorLength if ($constructorLength < $leastConstructorLength);
2614 }
2615 }
2616
2617 return $leastConstructorLength;
2618 }
2619
2620 sub GenerateConstructorCallback
2621 {
2622 my $interface = shift;
2623
2624 my $implClassName = GetImplName($interface);
2625 my $v8ClassName = GetV8ClassName($interface);
2626 my $code = "";
2627 $code .= "void ${v8ClassName}::constructorCallback(const v8::FunctionCallbac kInfo<v8::Value>& args)\n";
2628 $code .= "{\n";
2629 $code .= " TRACE_EVENT_SCOPED_SAMPLING_STATE(\"Blink\", \"DOMConstructor\ ");\n";
2630 $code .= GenerateFeatureObservation($interface->extendedAttributes->{"Measur eAs"});
2631 $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"D eprecateAs"});
2632 $code .= GenerateConstructorHeader();
2633 if (HasCustomConstructor($interface)) {
2634 $code .= " ${v8ClassName}::constructorCustom(args);\n";
2635 } else {
2636 $code .= " ${implClassName}V8Internal::constructor(args);\n";
2637 }
2638 $code .= "}\n\n";
2639 $implementation{nameSpaceWebCore}->add($code);
2640 }
2641
2642 sub GenerateConstructor
2643 {
2644 my $interface = shift;
2645
2646 if (@{$interface->constructors} == 1) {
2647 GenerateSingleConstructorCallback($interface, @{$interface->constructors }[0]);
2648 } else {
2649 foreach my $constructor (@{$interface->constructors}) {
2650 GenerateSingleConstructorCallback($interface, $constructor);
2651 }
2652 GenerateOverloadedConstructorCallback($interface);
2653 }
2654 }
2655
2656 sub GenerateEventConstructor
2657 {
2658 my $interface = shift;
2659 my $implClassName = GetImplName($interface);
2660 my $v8ClassName = GetV8ClassName($interface);
2661
2662 my @anyAttributeNames;
2663 my @serializableAnyAttributeNames;
2664 foreach my $attribute (@{$interface->attributes}) {
2665 if ($attribute->type eq "any") {
2666 push(@anyAttributeNames, $attribute->name);
2667 if (!$attribute->extendedAttributes->{"Unserializable"}) {
2668 push(@serializableAnyAttributeNames, $attribute->name);
2669 }
2670 }
2671 }
2672
2673 AddToImplIncludes("bindings/v8/Dictionary.h");
2674 $implementation{nameSpaceInternal}->add(<<END);
2675 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& args)
2676 {
2677 if (args.Length() < 1) {
2678 throwNotEnoughArgumentsError(args.GetIsolate());
2679 return;
2680 }
2681
2682 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, args[0]);
2683 END
2684
2685 foreach my $attrName (@anyAttributeNames) {
2686 $implementation{nameSpaceInternal}->add(" v8::Local<v8::Value> ${attr Name};\n");
2687 }
2688
2689 $implementation{nameSpaceInternal}->add(<<END);
2690 ${implClassName}Init eventInit;
2691 if (args.Length() >= 2) {
2692 V8TRYCATCH_VOID(Dictionary, options, Dictionary(args[1], args.GetIsolate ()));
2693 if (!fill${implClassName}Init(eventInit, options))
2694 return;
2695 END
2696
2697 # Store 'any'-typed properties on the wrapper to avoid leaking them between isolated worlds.
2698 foreach my $attrName (@anyAttributeNames) {
2699 $implementation{nameSpaceInternal}->add(<<END);
2700 options.get("${attrName}", ${attrName});
2701 if (!${attrName}.IsEmpty())
2702 args.Holder()->SetHiddenValue(V8HiddenPropertyName::${attrName}(), $ {attrName});
2703 END
2704 }
2705
2706 $implementation{nameSpaceInternal}->add(<<END);
2707 }
2708
2709 RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit);
2710 END
2711
2712 if (@serializableAnyAttributeNames) {
2713 # If we're in an isolated world, create a SerializedScriptValue and stor e it in the event for
2714 # later cloning if the property is accessed from another world.
2715 # The main world case is handled lazily (in Custom code).
2716 $implementation{nameSpaceInternal}->add(" if (isolatedWorldForIsolate (args.GetIsolate())) {\n");
2717 foreach my $attrName (@serializableAnyAttributeNames) {
2718 my $setter = "setSerialized" . FirstLetterToUpperCase($attrName);
2719 $implementation{nameSpaceInternal}->add(<<END);
2720 if (!${attrName}.IsEmpty())
2721 event->${setter}(SerializedScriptValue::createAndSwallowExceptions($ {attrName}, args.GetIsolate()));
2722 END
2723 }
2724 $implementation{nameSpaceInternal}->add(" }\n\n");
2725 }
2726
2727 $implementation{nameSpaceInternal}->add(<<END);
2728 v8::Handle<v8::Object> wrapper = args.Holder();
2729 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(event.release(), &$ {v8ClassName}::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent );
2730 v8SetReturnValue(args, wrapper);
2731 }
2732 END
2733
2734 my $code = "";
2735 $code .= <<END;
2736 bool fill${implClassName}Init(${implClassName}Init& eventInit, const Dictionary& options)
2737 {
2738 END
2739
2740 if ($interface->parent) {
2741 my $interfaceBase = $interface->parent;
2742 $code .= <<END;
2743 if (!fill${interfaceBase}Init(eventInit, options))
2744 return false;
2745
2746 END
2747 }
2748
2749 foreach my $attribute (@{$interface->attributes}) {
2750 if ($attribute->extendedAttributes->{"InitializedByEventConstructor"}) {
2751 if ($attribute->type ne "any") {
2752 my $attributeName = $attribute->name;
2753 my $attributeImplName = GetImplName($attribute);
2754 my $deprecation = $attribute->extendedAttributes->{"DeprecateAs" };
2755 my $dictionaryGetter = "options.get(\"$attributeName\", eventIni t.$attributeImplName)";
2756 if ($attribute->extendedAttributes->{"DeprecateAs"}) {
2757 $code .= " if ($dictionaryGetter)\n";
2758 $code .= " " . GenerateDeprecationNotification($attribute ->extendedAttributes->{"DeprecateAs"});
2759 } else {
2760 $code .= " $dictionaryGetter;\n";
2761 }
2762 }
2763 }
2764 }
2765
2766 $code .= <<END;
2767 return true;
2768 }
2769
2770 END
2771 $implementation{nameSpaceWebCore}->add($code);
2772 }
2773
2774 sub GenerateNamedConstructor
2775 {
2776 my $function = shift;
2777 my $interface = shift;
2778
2779 my $implClassName = GetImplName($interface);
2780 my $v8ClassName = GetV8ClassName($interface);
2781 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
2782 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2783 $raisesExceptions = 1;
2784 }
2785
2786 my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttr ibutes->{"MeasureAs"});
2787 my $maybeDeprecateFeature = GenerateDeprecationNotification($function->exten dedAttributes->{"DeprecateAs"});
2788
2789 my @beforeArgumentList;
2790 my @afterArgumentList;
2791
2792 my $toActiveDOMObject = "0";
2793 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
2794 $toActiveDOMObject = "${v8ClassName}::toActiveDOMObject";
2795 }
2796
2797 my $toEventTarget = "0";
2798 if (InheritsInterface($interface, "EventTarget")) {
2799 $toEventTarget = "${v8ClassName}::toEventTarget";
2800 }
2801
2802 $implementation{nameSpaceWebCore}->add(<<END);
2803 WrapperTypeInfo ${v8ClassName}Constructor::info = { ${v8ClassName}Constructor::G etTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, 0, ${v8ClassName}::installPerContextPrototypeProperties, 0, WrapperTypeObjectProtot ype };
2804
2805 END
2806
2807 my $code = "";
2808 $code .= <<END;
2809 static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8: :Value>& args)
2810 {
2811 END
2812 $code .= $maybeObserveFeature if $maybeObserveFeature;
2813 $code .= $maybeDeprecateFeature if $maybeDeprecateFeature;
2814 $code .= GenerateConstructorHeader();
2815 AddToImplIncludes("V8Document.h");
2816 $code .= <<END;
2817 Document* document = currentDocument();
2818 ASSERT(document);
2819
2820 // Make sure the document is added to the DOM Node map. Otherwise, the ${imp lClassName} instance
2821 // may end up being the only node in the map and get garbage-collected prema turely.
2822 toV8(document, args.Holder(), args.GetIsolate());
2823
2824 END
2825
2826 $code .= GenerateArgumentsCountCheck($function, $interface);
2827
2828 if ($raisesExceptions) {
2829 AddToImplIncludes("bindings/v8/ExceptionState.h");
2830 $code .= " ExceptionState es(args.GetIsolate());\n";
2831 }
2832
2833 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface);
2834 $code .= $parameterCheckString;
2835
2836 push(@beforeArgumentList, "*document");
2837
2838 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2839 push(@afterArgumentList, "es");
2840 }
2841
2842 my @argumentList;
2843 my $index = 0;
2844 foreach my $parameter (@{$function->parameters}) {
2845 last if $index eq $paramIndex;
2846 if ($replacements{$parameter->name}) {
2847 push(@argumentList, $replacements{$parameter->name});
2848 } else {
2849 push(@argumentList, $parameter->name);
2850 }
2851 $index++;
2852 }
2853
2854 my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterAr gumentList);
2855 $code .= "\n";
2856 $code .= " RefPtr<${implClassName}> impl = ${implClassName}::createForJSC onstructor(${argumentString});\n";
2857 $code .= " v8::Handle<v8::Object> wrapper = args.Holder();\n";
2858
2859 if ($interface->extendedAttributes->{"ConstructorRaisesException"}) {
2860 $code .= " if (es.throwIfNeeded())\n";
2861 $code .= " return;\n";
2862 }
2863
2864 $code .= <<END;
2865
2866 V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${ v8ClassName}Constructor::info, wrapper, args.GetIsolate(), WrapperConfiguration: :Dependent);
2867 args.GetReturnValue().Set(wrapper);
2868 }
2869
2870 END
2871 $implementation{nameSpaceWebCore}->add($code);
2872
2873 $code = <<END;
2874 v8::Handle<v8::FunctionTemplate> ${v8ClassName}Constructor::GetTemplate(v8::Isol ate* isolate, WrapperWorldType currentWorldType)
2875 {
2876 // This is only for getting a unique pointer which we can pass to privateTem plate.
2877 static const char* privateTemplateUniqueKey = "${v8ClassName}Constructor::Ge tTemplatePrivateTemplate";
2878 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
2879 v8::Handle<v8::FunctionTemplate> result = data->privateTemplateIfExists(curr entWorldType, &privateTemplateUniqueKey);
2880 if (!result.IsEmpty())
2881 return result;
2882
2883 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink\", \"BuildDOMTemplate");
2884 v8::HandleScope scope(isolate);
2885 result = v8::FunctionTemplate::New(${v8ClassName}ConstructorCallback);
2886
2887 v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
2888 instance->SetInternalFieldCount(${v8ClassName}::internalFieldCount);
2889 result->SetClassName(v8::String::NewSymbol("${implClassName}"));
2890 result->Inherit(${v8ClassName}::GetTemplate(isolate, currentWorldType));
2891 data->setPrivateTemplate(currentWorldType, &privateTemplateUniqueKey, result );
2892
2893 return scope.Close(result);
2894 }
2895
2896 END
2897 $implementation{nameSpaceWebCore}->add($code);
2898 }
2899
2900 sub GenerateConstructorHeader
2901 {
2902 AddToImplIncludes("bindings/v8/V8ObjectConstructor.h");
2903 my $content = <<END;
2904 if (!args.IsConstructCall()) {
2905 throwTypeError("DOM object constructor cannot be called as a function.", args.GetIsolate());
2906 return;
2907 }
2908
2909 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
2910 args.GetReturnValue().Set(args.Holder());
2911 return;
2912 }
2913
2914 END
2915 return $content;
2916 }
2917
2918 sub GenerateAttributeConfigurationArray
2919 {
2920 my $interface = shift;
2921 my $attributes = shift;
2922 my $code = "";
2923
2924 foreach my $attribute (@$attributes) {
2925 my $conditionalString = GenerateConditionalString($attribute);
2926 my $subCode = "";
2927 $subCode .= "#if ${conditionalString}\n" if $conditionalString;
2928 $subCode .= GenerateAttributeConfiguration($interface, $attribute, ",", "");
2929 $subCode .= "#endif // ${conditionalString}\n" if $conditionalString;
2930 $code .= $subCode;
2931 }
2932 return $code;
2933 }
2934
2935 sub GenerateAttributeConfiguration
2936 {
2937 my $interface = shift;
2938 my $attribute = shift;
2939 my $delimiter = shift;
2940 my $indent = shift;
2941 my $code = "";
2942 my $attrName = $attribute->name;
2943 my $attrExt = $attribute->extendedAttributes;
2944 my $implClassName = GetImplName($interface);
2945
2946 my $accessControl = "v8::DEFAULT";
2947 if ($attrExt->{"DoNotCheckSecurityOnGetter"}) {
2948 $accessControl = "v8::ALL_CAN_READ";
2949 } elsif ($attrExt->{"DoNotCheckSecurityOnSetter"}) {
2950 $accessControl = "v8::ALL_CAN_WRITE";
2951 } elsif ($attrExt->{"DoNotCheckSecurity"}) {
2952 $accessControl = "v8::ALL_CAN_READ";
2953 if (!IsReadonly($attribute)) {
2954 $accessControl .= " | v8::ALL_CAN_WRITE";
2955 }
2956 }
2957 if ($attrExt->{"Unforgeable"}) {
2958 $accessControl .= " | v8::PROHIBITS_OVERWRITING";
2959 }
2960 $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")";
2961
2962 my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attrExt) || "";
2963 if ($customAccessor eq "VALUE_IS_MISSING") {
2964 # use the naming convension, interface + (capitalize) attr name
2965 $customAccessor = $implClassName . "::" . $attrName;
2966 }
2967
2968 my $getter;
2969 my $setter;
2970 my $getterForMainWorld;
2971 my $setterForMainWorld;
2972 my $propAttribute = "v8::None";
2973
2974 my $isConstructor = ($attribute->type =~ /Constructor$/);
2975
2976 # Check attributes.
2977 # As per Web IDL specification, constructor properties on the ECMAScript glo bal object should be
2978 # configurable and should not be enumerable.
2979 if ($attrExt->{"NotEnumerable"} || $isConstructor) {
2980 $propAttribute .= " | v8::DontEnum";
2981 }
2982 if ($attrExt->{"Unforgeable"} && !$isConstructor) {
2983 $propAttribute .= " | v8::DontDelete";
2984 }
2985
2986 my $on_proto = "0 /* on instance */";
2987 my $data = "0"; # no data
2988
2989 # Constructor
2990 if ($isConstructor) {
2991 my $constructorType = $attribute->type;
2992 $constructorType =~ s/Constructor$//;
2993 # $constructorType ~= /Constructor$/ indicates that it is NamedConstruct or.
2994 # We do not generate the header file for NamedConstructor of class XXXX,
2995 # since we generate the NamedConstructor declaration into the header fil e of class XXXX.
2996 if ($constructorType !~ /Constructor$/ || $attribute->extendedAttributes ->{"CustomConstructor"}) {
2997 AddToImplIncludes("V8${constructorType}.h");
2998 }
2999 $data = "&V8${constructorType}::info";
3000 $getter = "${implClassName}V8Internal::${implClassName}ConstructorGetter ";
3001 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttrib uteSetterCallback";
3002 $getterForMainWorld = "0";
3003 $setterForMainWorld = "0";
3004 } else {
3005 # Default Getter and Setter
3006 $getter = "${implClassName}V8Internal::${attrName}AttributeGetterCallbac k";
3007 $setter = "${implClassName}V8Internal::${attrName}AttributeSetterCallbac k";
3008 $getterForMainWorld = "${getter}ForMainWorld";
3009 $setterForMainWorld = "${setter}ForMainWorld";
3010
3011 if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) {
3012 $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAt tributeSetterCallback";
3013 $setterForMainWorld = "0";
3014 }
3015 }
3016
3017 # Read only attributes
3018 if (IsReadonly($attribute)) {
3019 $setter = "0";
3020 $setterForMainWorld = "0";
3021 }
3022
3023 # An accessor can be installed on the proto
3024 if ($attrExt->{"OnProto"}) {
3025 $on_proto = "1 /* on proto */";
3026 }
3027
3028 if (!$attrExt->{"PerWorldBindings"}) {
3029 $getterForMainWorld = "0";
3030 $setterForMainWorld = "0";
3031 }
3032
3033 $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMainWorl d, $setterForMainWorld, $data, $accessControl, static_cast<v8::PropertyAttribute >($propAttribute), $on_proto}" . $delimiter . "\n";
3034 return $code;
3035 }
3036
3037 sub IsStandardFunction
3038 {
3039 my $interface = shift;
3040 my $function = shift;
3041
3042 my $interfaceName = $interface->name;
3043 my $attrExt = $function->extendedAttributes;
3044 return 0 if $attrExt->{"Unforgeable"};
3045 return 0 if $function->isStatic;
3046 return 0 if $attrExt->{"EnabledAtRuntime"};
3047 return 0 if $attrExt->{"EnabledPerContext"};
3048 return 0 if RequiresCustomSignature($function);
3049 return 0 if $attrExt->{"DoNotCheckSignature"};
3050 return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttrib utes->{"CheckSecurity"} || $interfaceName eq "Window"));
3051 return 0 if $attrExt->{"NotEnumerable"};
3052 return 0 if $attrExt->{"ReadOnly"};
3053 return 1;
3054 }
3055
3056 sub GenerateNonStandardFunction
3057 {
3058 my $interface = shift;
3059 my $function = shift;
3060 my $code = "";
3061
3062 my $implClassName = GetImplName($interface);
3063 my $attrExt = $function->extendedAttributes;
3064 my $name = $function->name;
3065
3066 my $property_attributes = "v8::DontDelete";
3067 if ($attrExt->{"NotEnumerable"}) {
3068 $property_attributes .= " | v8::DontEnum";
3069 }
3070 if ($attrExt->{"ReadOnly"}) {
3071 $property_attributes .= " | v8::ReadOnly";
3072 }
3073
3074 my $commentInfo = "Function '$name' (Extended Attributes: '" . join(' ', key s(%{$attrExt})) . "')";
3075
3076 my $template = "proto";
3077 if ($attrExt->{"Unforgeable"}) {
3078 $template = "instance";
3079 }
3080 if ($function->isStatic) {
3081 $template = "desc";
3082 }
3083
3084 my $conditional = "";
3085 if ($attrExt->{"EnabledAtRuntime"}) {
3086 # Only call Set()/SetAccessor() if this method should be enabled
3087 my $enable_function = GetRuntimeEnableFunctionName($function);
3088 $conditional = "if (${enable_function}())\n ";
3089 }
3090 if ($attrExt->{"EnabledPerContext"}) {
3091 # Only call Set()/SetAccessor() if this method should be enabled
3092 my $enable_function = GetContextEnableFunction($function);
3093 $conditional = "if (${enable_function}(impl->document()))\n ";
3094 }
3095
3096 if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCh eckSecurity"}) {
3097 my $setter = $attrExt->{"ReadOnly"} ? "0" : "${implClassName}V8Internal: :${implClassName}DomainSafeFunctionSetter";
3098 # Functions that are marked DoNotCheckSecurity are always readable but i f they are changed
3099 # and then accessed on a different domain we do not return the underlyin g value but instead
3100 # return a new copy of the original function. This is achieved by storin g the changed value
3101 # as hidden property.
3102 $code .= <<END;
3103
3104 // $commentInfo
3105 ${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));
3106 END
3107 return $code;
3108 }
3109
3110 my $signature = "defaultSignature";
3111 if ($attrExt->{"DoNotCheckSignature"} || $function->isStatic) {
3112 $signature = "v8::Local<v8::Signature>()";
3113 }
3114
3115 my $conditionalString = GenerateConditionalString($function);
3116 $code .= "#if ${conditionalString}\n" if $conditionalString;
3117 if (RequiresCustomSignature($function)) {
3118 $signature = "${name}Signature";
3119 $code .= "\n // Custom Signature '$name'\n" . CreateCustomSignature($ function);
3120 }
3121
3122 if ($property_attributes eq "v8::DontDelete") {
3123 $property_attributes = "";
3124 } else {
3125 $property_attributes = ", static_cast<v8::PropertyAttribute>($property_a ttributes)";
3126 }
3127
3128 if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSign ature" && $property_attributes eq "") {
3129 die "This shouldn't happen: Class '$implClassName' $commentInfo\n";
3130 }
3131
3132 my $functionLength = GetFunctionLength($function);
3133
3134 if ($function->extendedAttributes->{"PerWorldBindings"}) {
3135 $code .= " if (currentWorldType == MainWorld) {\n";
3136 $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$ name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCall backForMainWorld, v8Undefined(), ${signature}, $functionLength)$property_attribu tes);\n";
3137 $code .= " } else {\n";
3138 $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$ name\"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCall back, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n";
3139 $code .= " }\n";
3140 } else {
3141 $code .= " ${conditional}$template->Set(v8::String::NewSymbol(\"$name \"), v8::FunctionTemplate::New(${implClassName}V8Internal::${name}MethodCallback , v8Undefined(), ${signature}, $functionLength)$property_attributes);\n";
3142 }
3143 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
3144 return $code;
3145 }
3146
3147 sub GenerateIsNullExpression
3148 {
3149 my $type = shift;
3150 my $variableName = shift;
3151 if (IsUnionType($type)) {
3152 my $types = $type->unionMemberTypes;
3153 my @expression = ();
3154 for my $i (0 .. scalar(@$types)-1) {
3155 my $unionMemberType = $types->[$i];
3156 my $unionMemberVariable = $variableName . $i;
3157 my $isNull = GenerateIsNullExpression($unionMemberType, $unionMember Variable);
3158 push @expression, $isNull;
3159 }
3160 return join " && ", @expression;
3161 }
3162 if (IsRefPtrType($type)) {
3163 return "!${variableName}";
3164 } elsif ($type eq "DOMString") {
3165 return "${variableName}.isNull()";
3166 } elsif ($type eq "Promise") {
3167 return "${variableName}.isNull()";
3168 } else {
3169 return "";
3170 }
3171 }
3172
3173 sub GenerateIfElseStatement
3174 {
3175 my $type = shift;
3176 my $outputVariableName = shift;
3177 my $conditions = shift;
3178 my $statements = shift;
3179
3180 my $code = "";
3181 if (@$conditions == 1) {
3182 $code .= " ${type} ${outputVariableName} = " . $statements->[0] . "\n ";
3183 } else {
3184 $code .= " ${type} ${outputVariableName};\n";
3185 for my $i (0 .. @$conditions - 1) {
3186 my $token = "else if";
3187 $token = "if" if $i == 0;
3188 $token = "else" if $i == @$conditions - 1;
3189 $code .= " ${token}";
3190 $code .= " (" . $conditions->[$i] . ")" if $conditions->[$i];
3191 $code .= "\n";
3192 $code .= " ${outputVariableName} = " . $statements->[$i] . "\ n";
3193 }
3194 }
3195 return $code;
3196 }
3197
3198 sub GenerateImplementationIndexedPropertyAccessors
3199 {
3200 my $interface = shift;
3201 my $interfaceName = $interface->name;
3202 my $implClassName = GetImplName($interface);
3203 my $v8ClassName = GetV8ClassName($interface);
3204
3205 my $indexedGetterFunction = GetIndexedGetterFunction($interface);
3206 if ($indexedGetterFunction) {
3207 my $hasCustomIndexedGetter = $indexedGetterFunction->extendedAttributes- >{"Custom"};
3208 if (!$hasCustomIndexedGetter) {
3209 GenerateImplementationIndexedPropertyGetter($interface, $indexedGett erFunction);
3210 }
3211 GenerateImplementationIndexedPropertyGetterCallback($interface, $hasCust omIndexedGetter);
3212 }
3213
3214 my $indexedSetterFunction = GetIndexedSetterFunction($interface);
3215 if ($indexedSetterFunction) {
3216 my $hasCustomIndexedSetter = $indexedSetterFunction->extendedAttributes- >{"Custom"};
3217 if (!$hasCustomIndexedSetter) {
3218 GenerateImplementationIndexedPropertySetter($interface, $indexedSett erFunction);
3219 }
3220 GenerateImplementationIndexedPropertySetterCallback($interface, $hasCust omIndexedSetter);
3221 }
3222
3223 my $indexedDeleterFunction = GetIndexedDeleterFunction($interface);
3224 if ($indexedDeleterFunction) {
3225 my $hasCustomIndexedDeleter = $indexedDeleterFunction->extendedAttribute s->{"Custom"};
3226 if (!$hasCustomIndexedDeleter) {
3227 GenerateImplementationIndexedPropertyDeleter($interface, $indexedDel eterFunction);
3228 }
3229 GenerateImplementationIndexedPropertyDeleterCallback($interface, $hasCus tomIndexedDeleter);
3230 }
3231
3232 my $indexedEnumeratorFunction = $indexedGetterFunction;
3233 $indexedEnumeratorFunction = 0 if $indexedGetterFunction && $indexedGetterFu nction->extendedAttributes->{"NotEnumerable"};
3234
3235 my $indexedQueryFunction = 0;
3236 # If there is an enumerator, there MUST be a query method to properly commun icate property attributes.
3237 my $hasQuery = $indexedQueryFunction || $indexedEnumeratorFunction;
3238
3239 my $setOn = "Instance";
3240
3241 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallba cks) and it's used on Window
3242 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
3243 # get implementation straight out of the Window prototype regardless of what prototype is actually set
3244 # on the object.
3245 if ($interfaceName eq "Window") {
3246 $setOn = "Prototype";
3247 }
3248
3249 my $code = "";
3250 if ($indexedGetterFunction || $indexedSetterFunction || $indexedDeleterFunct ion || $indexedEnumeratorFunction || $hasQuery) {
3251 $code .= " desc->${setOn}Template()->SetIndexedPropertyHandler(${impl ClassName}V8Internal::indexedPropertyGetterCallback";
3252 $code .= $indexedSetterFunction ? ", ${implClassName}V8Internal::indexed PropertySetterCallback" : ", 0";
3253 $code .= ", 0"; # IndexedPropertyQuery -- not being used at the moment.
3254 $code .= $indexedDeleterFunction ? ", ${implClassName}V8Internal::indexe dPropertyDeleterCallback" : ", 0";
3255 $code .= $indexedEnumeratorFunction ? ", indexedPropertyEnumerator<${imp lClassName}>" : ", 0";
3256 $code .= ");\n";
3257 }
3258
3259 return $code;
3260 }
3261
3262 sub GenerateImplementationIndexedPropertyGetter
3263 {
3264 my $interface = shift;
3265 my $indexedGetterFunction = shift;
3266 my $implClassName = GetImplName($interface);
3267 my $v8ClassName = GetV8ClassName($interface);
3268 my $methodName = GetImplName($indexedGetterFunction);
3269
3270 my $returnType = $indexedGetterFunction->type;
3271 my $nativeType = GetNativeType($returnType);
3272 my $nativeValue = "element";
3273 $nativeValue .= ".release()" if (IsRefPtrType($returnType));
3274 my $isNull = GenerateIsNullExpression($returnType, "element");
3275 my $returnJSValueCode = NativeToJSValue($indexedGetterFunction->type, $index edGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.Holder()", "info.GetIsolate()", "info", "collection", "", "return");
3276 my $raisesExceptions = $indexedGetterFunction->extendedAttributes->{"RaisesE xception"};
3277 my $methodCallCode = GenerateMethodCall($returnType, "element", "collection- >${methodName}", "index", $raisesExceptions);
3278 my $getterCode = "static void indexedPropertyGetter(uint32_t index, const v8 ::PropertyCallbackInfo<v8::Value>& info)\n";
3279 $getterCode .= "{\n";
3280 $getterCode .= " ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n" ;
3281 $getterCode .= " ${implClassName}* collection = ${v8ClassName}::toNative( info.Holder());\n";
3282 if ($raisesExceptions) {
3283 $getterCode .= " ExceptionState es(info.GetIsolate());\n";
3284 }
3285 $getterCode .= $methodCallCode . "\n";
3286 if ($raisesExceptions) {
3287 $getterCode .= " if (es.throwIfNeeded())\n";
3288 $getterCode .= " return;\n";
3289 }
3290 if (IsUnionType($returnType)) {
3291 $getterCode .= "${returnJSValueCode}\n";
3292 $getterCode .= " return;\n";
3293 } else {
3294 $getterCode .= " if (${isNull})\n";
3295 $getterCode .= " return;\n";
3296 $getterCode .= $returnJSValueCode . "\n";
3297 }
3298 $getterCode .= "}\n\n";
3299 $implementation{nameSpaceInternal}->add($getterCode);
3300 }
3301
3302 sub GenerateImplementationIndexedPropertyGetterCallback
3303 {
3304 my $interface = shift;
3305 my $hasCustom = shift;
3306 my $implClassName = GetImplName($interface);
3307 my $v8ClassName = GetV8ClassName($interface);
3308
3309 my $code = "static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3310 $code .= "{\n";
3311 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty \");\n";
3312 if ($hasCustom) {
3313 $code .= " ${v8ClassName}::indexedPropertyGetterCustom(index, info);\ n";
3314 } else {
3315 $code .= " ${implClassName}V8Internal::indexedPropertyGetter(index, i nfo);\n";
3316 }
3317 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
3318 $code .= "}\n\n";
3319 $implementation{nameSpaceInternal}->add($code);
3320 }
3321
3322 sub GenerateImplementationIndexedPropertySetterCallback
3323 {
3324 my $interface = shift;
3325 my $hasCustom = shift;
3326 my $implClassName = GetImplName($interface);
3327 my $v8ClassName = GetV8ClassName($interface);
3328
3329 my $code = "static void indexedPropertySetterCallback(uint32_t index, v8::Lo cal<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3330 $code .= "{\n";
3331 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty \");\n";
3332 if ($hasCustom) {
3333 $code .= " ${v8ClassName}::indexedPropertySetterCustom(index, value, info);\n";
3334 } else {
3335 $code .= " ${implClassName}V8Internal::indexedPropertySetter(index, v alue, info);\n";
3336 }
3337 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
3338 $code .= "}\n\n";
3339 $implementation{nameSpaceInternal}->add($code);
3340 }
3341
3342 sub GenerateImplementationIndexedPropertyDeleterCallback
3343 {
3344 my $interface = shift;
3345 my $hasCustom = shift;
3346 my $implClassName = GetImplName($interface);
3347 my $v8ClassName = GetV8ClassName($interface);
3348
3349 my $code = "static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
3350 $code .= "{\n";
3351 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty \");\n";
3352 if ($hasCustom) {
3353 $code .= " ${v8ClassName}::indexedPropertyDeleterCustom(index, info); \n";
3354 } else {
3355 $code .= " ${implClassName}V8Internal::indexedPropertyDeleter(index, info);\n";
3356 }
3357 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
3358 $code .= "}\n\n";
3359 $implementation{nameSpaceInternal}->add($code);
3360 }
3361
3362 sub GenerateImplementationIndexedPropertySetter
3363 {
3364 my $interface = shift;
3365 my $indexedSetterFunction = shift;
3366 my $implClassName = GetImplName($interface);
3367 my $v8ClassName = GetV8ClassName($interface);
3368 my $methodName = GetImplName($indexedSetterFunction);
3369
3370 my $type = $indexedSetterFunction->parameters->[1]->type;
3371 my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesE xception"};
3372 my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttribute s->{"TreatNullAs"};
3373 my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttr ibutes->{"TreatUndefinedAs"};
3374 my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8:: Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3375 $code .= "{\n";
3376 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n";
3377 $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->t ype, $indexedSetterFunction->extendedAttributes, "value", "propertyValue", " ", "info.GetIsolate()");
3378
3379 my $extraArguments = "";
3380 if ($raisesExceptions) {
3381 $code .= " ExceptionState es(info.GetIsolate());\n";
3382 $extraArguments = ", es";
3383 }
3384 my @conditions = ();
3385 my @statements = ();
3386 if ($treatNullAs && $treatNullAs ne "NullString") {
3387 push @conditions, "value->IsNull()";
3388 push @statements, "collection->${treatNullAs}(index$extraArguments);";
3389 }
3390 if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") {
3391 push @conditions, "value->IsUndefined()";
3392 push @statements, "collection->${treatUndefinedAs}(index$extraArguments) ;";
3393 }
3394 push @conditions, "";
3395 push @statements, "collection->${methodName}(index, propertyValue$extraArgum ents);";
3396 $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statement s);
3397
3398 $code .= " if (!result)\n";
3399 $code .= " return;\n";
3400 if ($raisesExceptions) {
3401 $code .= " if (es.throwIfNeeded())\n";
3402 $code .= " return;\n";
3403 }
3404 $code .= " v8SetReturnValue(info, value);\n";
3405 $code .= "}\n\n";
3406 $implementation{nameSpaceInternal}->add($code);
3407 }
3408
3409 sub GenerateImplementationNamedPropertyAccessors
3410 {
3411 my $interface = shift;
3412
3413 my $interfaceName = $interface->name;
3414 my $implClassName = GetImplName($interface);
3415 my $v8ClassName = GetV8ClassName($interface);
3416
3417 my $namedGetterFunction = GetNamedGetterFunction($interface);
3418 if ($namedGetterFunction) {
3419 my $hasCustomNamedGetter = $namedGetterFunction->extendedAttributes->{"C ustom"};
3420 if (!$hasCustomNamedGetter) {
3421 GenerateImplementationNamedPropertyGetter($interface, $namedGetterFu nction);
3422 }
3423 GenerateImplementationNamedPropertyGetterCallback($interface, $hasCustom NamedGetter);
3424 }
3425
3426 my $namedSetterFunction = GetNamedSetterFunction($interface);
3427 if ($namedSetterFunction) {
3428 my $hasCustomNamedSetter = $namedSetterFunction->extendedAttributes->{"C ustom"};
3429 if (!$hasCustomNamedSetter) {
3430 GenerateImplementationNamedPropertySetter($interface, $namedSetterFu nction);
3431 }
3432 GenerateImplementationNamedPropertySetterCallback($interface, $hasCustom NamedSetter);
3433 }
3434
3435 my $namedDeleterFunction = GetNamedDeleterFunction($interface);
3436 if ($namedDeleterFunction) {
3437 my $hasCustomNamedDeleter = $namedDeleterFunction->extendedAttributes->{ "Custom"};
3438 if (!$hasCustomNamedDeleter) {
3439 GenerateImplementationNamedPropertyDeleter($interface, $namedDeleter Function);
3440 }
3441 GenerateImplementationNamedPropertyDeleterCallback($interface, $hasCusto mNamedDeleter);
3442 }
3443
3444 my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction- >extendedAttributes->{"NotEnumerable"};
3445 if ($namedEnumeratorFunction) {
3446 my $hasCustomNamedEnumerator = $namedGetterFunction->extendedAttributes- >{"CustomEnumerateProperty"};
3447 if (!$hasCustomNamedEnumerator) {
3448 GenerateImplementationNamedPropertyEnumerator($interface);
3449 GenerateImplementationNamedPropertyQuery($interface);
3450 }
3451 GenerateImplementationNamedPropertyEnumeratorCallback($interface, $hasCu stomNamedEnumerator);
3452 GenerateImplementationNamedPropertyQueryCallback($interface, $hasCustomN amedEnumerator);
3453 }
3454
3455 my $subCode = "";
3456 if ($namedGetterFunction || $namedSetterFunction || $namedDeleterFunction || $namedEnumeratorFunction) {
3457 my $setOn = "Instance";
3458
3459 # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCa llbacks) and it's used on Window
3460 # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to
3461 # get implementation straight out of the Window prototype regardless of what prototype is actually set
3462 # on the object.
3463 if ($interfaceName eq "Window") {
3464 $setOn = "Prototype";
3465 }
3466
3467 $subCode .= " desc->${setOn}Template()->SetNamedPropertyHandler(";
3468 $subCode .= $namedGetterFunction ? "${implClassName}V8Internal::namedPro pertyGetterCallback, " : "0, ";
3469 $subCode .= $namedSetterFunction ? "${implClassName}V8Internal::namedPro pertySetterCallback, " : "0, ";
3470 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::name dPropertyQueryCallback, " : "0, ";
3471 $subCode .= $namedDeleterFunction ? "${implClassName}V8Internal::namedPr opertyDeleterCallback, " : "0, ";
3472 $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::name dPropertyEnumeratorCallback" : "0";
3473 $subCode .= ");\n";
3474 }
3475
3476 return $subCode;
3477 }
3478
3479 sub GenerateImplementationNamedPropertyGetterCallback
3480 {
3481 my $interface = shift;
3482 my $hasCustom = shift;
3483 my $implClassName = GetImplName($interface);
3484 my $v8ClassName = GetV8ClassName($interface);
3485
3486 my $code = "static void namedPropertyGetterCallback(v8::Local<v8::String> na me, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3487 $code .= "{\n";
3488 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3489 if ($hasCustom) {
3490 $code .= " ${v8ClassName}::namedPropertyGetterCustom(name, info);\n";
3491 } else {
3492 $code .= " ${implClassName}V8Internal::namedPropertyGetter(name, info );\n";
3493 }
3494 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
3495 $code .= "}\n\n";
3496 $implementation{nameSpaceInternal}->add($code);
3497 }
3498
3499 sub GenerateImplementationNamedPropertySetterCallback
3500 {
3501 my $interface = shift;
3502 my $hasCustom = shift;
3503 my $implClassName = GetImplName($interface);
3504 my $v8ClassName = GetV8ClassName($interface);
3505
3506 my $code = "static void namedPropertySetterCallback(v8::Local<v8::String> na me, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) \n";
3507 $code .= "{\n";
3508 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3509 if ($hasCustom) {
3510 $code .= " ${v8ClassName}::namedPropertySetterCustom(name, value, inf o);\n";
3511 } else {
3512 $code .= " ${implClassName}V8Internal::namedPropertySetter(name, valu e, info);\n";
3513 }
3514 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
3515 $code .= "}\n\n";
3516 $implementation{nameSpaceInternal}->add($code);
3517 }
3518
3519 sub GenerateImplementationNamedPropertyDeleterCallback
3520 {
3521 my $interface = shift;
3522 my $hasCustom = shift;
3523 my $implClassName = GetImplName($interface);
3524 my $v8ClassName = GetV8ClassName($interface);
3525
3526 my $code = "static void namedPropertyDeleterCallback(v8::Local<v8::String> n ame, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
3527 $code .= "{\n";
3528 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3529 if ($hasCustom) {
3530 $code .= " ${v8ClassName}::namedPropertyDeleterCustom(name, info);\n" ;
3531 } else {
3532 $code .= " ${implClassName}V8Internal::namedPropertyDeleter(name, inf o);\n";
3533 }
3534 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
3535 $code .= "}\n\n";
3536 $implementation{nameSpaceInternal}->add($code);
3537 }
3538
3539 sub GenerateImplementationNamedPropertyEnumeratorCallback
3540 {
3541 my $interface = shift;
3542 my $hasCustom = shift;
3543 my $implClassName = GetImplName($interface);
3544 my $v8ClassName = GetV8ClassName($interface);
3545
3546 my $code = "static void namedPropertyEnumeratorCallback(const v8::PropertyCa llbackInfo<v8::Array>& info)\n";
3547 $code .= "{\n";
3548 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3549 if ($hasCustom) {
3550 $code .= " ${v8ClassName}::namedPropertyEnumeratorCustom(info);\n";
3551 } else {
3552 $code .= " ${implClassName}V8Internal::namedPropertyEnumerator(info); \n";
3553 }
3554 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
3555 $code .= "}\n\n";
3556 $implementation{nameSpaceInternal}->add($code);
3557 }
3558
3559 sub GenerateImplementationNamedPropertyQueryCallback
3560 {
3561 my $interface = shift;
3562 my $hasCustom = shift;
3563 my $implClassName = GetImplName($interface);
3564 my $v8ClassName = GetV8ClassName($interface);
3565
3566 my $code = "static void namedPropertyQueryCallback(v8::Local<v8::String> nam e, const v8::PropertyCallbackInfo<v8::Integer>& info)\n";
3567 $code .= "{\n";
3568 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\" );\n";
3569 if ($hasCustom) {
3570 $code .= " ${v8ClassName}::namedPropertyQueryCustom(name, info);\n";
3571 } else {
3572 $code .= " ${implClassName}V8Internal::namedPropertyQuery(name, info) ;\n";
3573 }
3574 $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n";
3575 $code .= "}\n\n";
3576 $implementation{nameSpaceInternal}->add($code);
3577 }
3578
3579 sub GenerateMethodCall
3580 {
3581 my $returnType = shift; # string or UnionType
3582 my $returnName = shift;
3583 my $functionExpression = shift;
3584 my $firstArgument = shift;
3585 my $raisesExceptions = shift;
3586
3587 my @arguments = ();
3588 push @arguments, $firstArgument;
3589 if ($raisesExceptions) {
3590 push @arguments, "es";
3591 }
3592
3593 if (IsUnionType($returnType)) {
3594 my $code = "";
3595 my @extraArguments = ();
3596 for my $i (0..scalar(@{$returnType->unionMemberTypes})-1) {
3597 my $unionMemberType = $returnType->unionMemberTypes->[$i];
3598 my $nativeType = GetNativeType($unionMemberType);
3599 my $unionMemberVariable = $returnName . $i;
3600 my $unionMemberEnabledVariable = $returnName . $i . "Enabled";
3601 $code .= " bool ${unionMemberEnabledVariable} = false;\n";
3602 $code .= " ${nativeType} ${unionMemberVariable};\n";
3603 push @extraArguments, $unionMemberEnabledVariable;
3604 push @extraArguments, $unionMemberVariable;
3605 }
3606 push @arguments, @extraArguments;
3607 $code .= " ${functionExpression}(" . (join ", ", @arguments) . ");";
3608 return $code;
3609 } else {
3610 my $nativeType = GetNativeType($returnType);
3611 return " ${nativeType} element = ${functionExpression}(" . (join ", " , @arguments) . ");"
3612 }
3613 }
3614
3615 sub GenerateImplementationNamedPropertyGetter
3616 {
3617 my $interface = shift;
3618 my $namedGetterFunction = shift;
3619 my $implClassName = GetImplName($interface);
3620 my $v8ClassName = GetV8ClassName($interface);
3621 my $methodName = GetImplName($namedGetterFunction);
3622
3623 my $returnType = $namedGetterFunction->type;
3624 my $isNull = GenerateIsNullExpression($returnType, "element");
3625 my $nativeValue = "element";
3626 $nativeValue .= ".release()" if (IsRefPtrType($returnType));
3627 my $returnJSValueCode = NativeToJSValue($namedGetterFunction->type, $namedGe tterFunction->extendedAttributes, $nativeValue, " ", "", "info.Holder()", "in fo.GetIsolate()", "info", "collection", "", "return");
3628 my $raisesExceptions = $namedGetterFunction->extendedAttributes->{"RaisesExc eption"};
3629 my $methodCallCode = GenerateMethodCall($returnType, "element", "collection- >${methodName}", "propertyName", $raisesExceptions);
3630
3631 my $code = "static void namedPropertyGetter(v8::Local<v8::String> name, cons t v8::PropertyCallbackInfo<v8::Value>& info)\n";
3632 $code .= "{\n";
3633 if (!$namedGetterFunction->extendedAttributes->{"OverrideBuiltins"}) {
3634 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n ame).IsEmpty())\n";
3635 $code .= " return;\n";
3636 $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n";
3637 $code .= " return;\n";
3638 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n";
3639 $code .= " return;\n";
3640 }
3641 $code .= "\n";
3642 $code .= " ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n";
3643 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n";
3644 $code .= " AtomicString propertyName = toWebCoreAtomicString(name);\n";
3645 if ($raisesExceptions) {
3646 $code .= " ExceptionState es(info.GetIsolate());\n";
3647 }
3648 $code .= $methodCallCode . "\n";
3649 if ($raisesExceptions) {
3650 $code .= " if (es.throwIfNeeded())\n";
3651 $code .= " return;\n";
3652 }
3653 if (IsUnionType($returnType)) {
3654 $code .= "${returnJSValueCode}\n";
3655 $code .= " return;\n";
3656 } else {
3657 $code .= " if (${isNull})\n";
3658 $code .= " return;\n";
3659 $code .= $returnJSValueCode . "\n";
3660 }
3661 $code .= "}\n\n";
3662 $implementation{nameSpaceInternal}->add($code);
3663 }
3664
3665 sub GenerateImplementationNamedPropertySetter
3666 {
3667 my $interface = shift;
3668 my $namedSetterFunction = shift;
3669 my $implClassName = GetImplName($interface);
3670 my $v8ClassName = GetV8ClassName($interface);
3671 my $methodName = GetImplName($namedSetterFunction);
3672
3673 my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesExc eption"};
3674 my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes- >{"TreatNullAs"};
3675 my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttrib utes->{"TreatUndefinedAs"};
3676
3677 my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8:: Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3678 $code .= "{\n";
3679 if (!$namedSetterFunction->extendedAttributes->{"OverrideBuiltins"}) {
3680 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n ame).IsEmpty())\n";
3681 $code .= " return;\n";
3682 $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n";
3683 $code .= " return;\n";
3684 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n";
3685 $code .= " return;\n";
3686 }
3687 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n";
3688 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->typ e, $namedSetterFunction->extendedAttributes, "name", "propertyName", " ", "in fo.GetIsolate()");
3689 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->typ e, $namedSetterFunction->extendedAttributes, "value", "propertyValue", " ", " info.GetIsolate()");
3690 my $extraArguments = "";
3691 if ($raisesExceptions) {
3692 $code .= " ExceptionState es(info.GetIsolate());\n";
3693 $extraArguments = ", es";
3694 }
3695
3696 my @conditions = ();
3697 my @statements = ();
3698 if ($treatNullAs && $treatNullAs ne "NullString") {
3699 push @conditions, "value->IsNull()";
3700 push @statements, "collection->${treatNullAs}(propertyName$extraArgument s);";
3701 }
3702 if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") {
3703 push @conditions, "value->IsUndefined()";
3704 push @statements, "collection->${treatUndefinedAs}(propertyName$extraArg uments);";
3705 }
3706 push @conditions, "";
3707 push @statements, "collection->${methodName}(propertyName, propertyValue$ext raArguments);";
3708 $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statement s);
3709
3710 $code .= " if (!result)\n";
3711 $code .= " return;\n";
3712 if ($raisesExceptions) {
3713 $code .= " if (es.throwIfNeeded())\n";
3714 $code .= " return;\n";
3715 }
3716 $code .= " v8SetReturnValue(info, value);\n";
3717 $code .= "}\n\n";
3718 $implementation{nameSpaceInternal}->add($code);
3719 }
3720
3721 sub GenerateImplementationIndexedPropertyDeleter
3722 {
3723 my $interface = shift;
3724 my $indexedDeleterFunction = shift;
3725 my $implClassName = GetImplName($interface);
3726 my $v8ClassName = GetV8ClassName($interface);
3727 my $methodName = GetImplName($indexedDeleterFunction);
3728
3729 my $raisesExceptions = $indexedDeleterFunction->extendedAttributes->{"Raises Exception"};
3730
3731 my $code = "static void indexedPropertyDeleter(unsigned index, const v8::Pro pertyCallbackInfo<v8::Boolean>& info)\n";
3732 $code .= "{\n";
3733 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n";
3734 my $extraArguments = "";
3735 if ($raisesExceptions) {
3736 $code .= " ExceptionState es(info.GetIsolate());\n";
3737 $extraArguments = ", es";
3738 }
3739 $code .= " bool result = collection->${methodName}(index$extraArguments); \n";
3740 if ($raisesExceptions) {
3741 $code .= " if (es.throwIfNeeded())\n";
3742 $code .= " return;\n";
3743 }
3744 $code .= " return v8SetReturnValueBool(info, result);\n";
3745 $code .= "}\n\n";
3746 $implementation{nameSpaceInternal}->add($code);
3747 }
3748
3749 sub GenerateImplementationNamedPropertyDeleter
3750 {
3751 my $interface = shift;
3752 my $namedDeleterFunction = shift;
3753 my $implClassName = GetImplName($interface);
3754 my $v8ClassName = GetV8ClassName($interface);
3755 my $methodName = GetImplName($namedDeleterFunction);
3756
3757 my $raisesExceptions = $namedDeleterFunction->extendedAttributes->{"RaisesEx ception"};
3758
3759 my $code = "static void namedPropertyDeleter(v8::Local<v8::String> name, con st v8::PropertyCallbackInfo<v8::Boolean>& info)\n";
3760 $code .= "{\n";
3761 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n";
3762 $code .= " AtomicString propertyName = toWebCoreAtomicString(name);\n";
3763 my $extraArguments = "";
3764 if ($raisesExceptions) {
3765 $code .= " ExceptionState es(info.GetIsolate());\n";
3766 $extraArguments = ", es";
3767 }
3768 $code .= " bool result = collection->${methodName}(propertyName$extraArgu ments);\n";
3769 if ($raisesExceptions) {
3770 $code .= " if (es.throwIfNeeded())\n";
3771 $code .= " return;\n";
3772 }
3773 $code .= " return v8SetReturnValueBool(info, result);\n";
3774 $code .= "}\n\n";
3775 $implementation{nameSpaceInternal}->add($code);
3776 }
3777
3778 sub GenerateImplementationNamedPropertyEnumerator
3779 {
3780 my $interface = shift;
3781 my $implClassName = GetImplName($interface);
3782 my $v8ClassName = GetV8ClassName($interface);
3783
3784 $implementation{nameSpaceInternal}->add(<<END);
3785 static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& i nfo)
3786 {
3787 ExceptionState es(info.GetIsolate());
3788 ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());
3789 Vector<String> names;
3790 collection->namedPropertyEnumerator(names, es);
3791 if (es.throwIfNeeded())
3792 return;
3793 v8::Handle<v8::Array> v8names = v8::Array::New(names.size());
3794 for (size_t i = 0; i < names.size(); ++i)
3795 v8names->Set(v8::Integer::New(i, info.GetIsolate()), v8String(names[i], info.GetIsolate()));
3796 v8SetReturnValue(info, v8names);
3797 }
3798
3799 END
3800 }
3801
3802 sub GenerateImplementationNamedPropertyQuery
3803 {
3804 my $interface = shift;
3805 my $implClassName = GetImplName($interface);
3806 my $v8ClassName = GetV8ClassName($interface);
3807
3808 $implementation{nameSpaceInternal}->add(<<END);
3809 static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCal lbackInfo<v8::Integer>& info)
3810 {
3811 ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());
3812 AtomicString propertyName = toWebCoreAtomicString(name);
3813 ExceptionState es(info.GetIsolate());
3814 bool result = collection->namedPropertyQuery(propertyName, es);
3815 if (es.throwIfNeeded())
3816 return;
3817 if (!result)
3818 return;
3819 v8SetReturnValueInt(info, v8::None);
3820 }
3821
3822 END
3823 }
3824
3825 sub GenerateImplementationLegacyCall
3826 {
3827 my $interface = shift;
3828 my $code = "";
3829
3830 my $v8ClassName = GetV8ClassName($interface);
3831
3832 if ($interface->extendedAttributes->{"CustomLegacyCall"}) {
3833 $code .= " desc->InstanceTemplate()->SetCallAsFunctionHandler(${v8Cla ssName}::legacyCallCustom);\n";
3834 }
3835 return $code;
3836 }
3837
3838 sub GenerateImplementationMasqueradesAsUndefined
3839 {
3840 my $interface = shift;
3841 my $code = "";
3842
3843 if ($interface->extendedAttributes->{"MasqueradesAsUndefined"})
3844 {
3845 $code .= " desc->InstanceTemplate()->MarkAsUndetectable();\n";
3846 }
3847 return $code;
3848 }
3849
3850 sub GenerateImplementation
3851 {
3852 my $object = shift;
3853 my $interface = shift;
3854 my $interfaceName = $interface->name;
3855 my $implClassName = GetImplName($interface);
3856 my $v8ClassName = GetV8ClassName($interface);
3857 my $nativeType = GetNativeTypeForConversions($interface);
3858
3859 AddToImplIncludes("bindings/v8/V8Binding.h");
3860 AddToImplIncludes("bindings/v8/V8DOMWrapper.h");
3861 AddToImplIncludes("core/dom/ContextFeatures.h");
3862 AddToImplIncludes("core/dom/Document.h");
3863 AddToImplIncludes("RuntimeEnabledFeatures.h");
3864 AddToImplIncludes("core/platform/chromium/TraceEvent.h");
3865
3866 AddIncludesForType($interfaceName);
3867
3868 my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObje ct") ? "${v8ClassName}::toActiveDOMObject" : "0";
3869 my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8Clas sName}::toEventTarget" : "0";
3870 my $rootForGC = NeedsOpaqueRootForGC($interface) ? "${v8ClassName}::opaqueRo otForGC" : "0";
3871
3872 # Find the super descriptor.
3873 my $parentClass = "";
3874 my $parentClassTemplate = "";
3875 if ($interface->parent) {
3876 my $parent = $interface->parent;
3877 AddToImplIncludes("V8${parent}.h");
3878 $parentClass = "V8" . $parent;
3879 $parentClassTemplate = $parentClass . "::GetTemplate(isolate, currentWor ldType)";
3880 }
3881
3882 my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0";
3883 my $WrapperTypePrototype = $interface->isException ? "WrapperTypeErrorProtot ype" : "WrapperTypeObjectPrototype";
3884
3885 if (!IsSVGTypeNeedingTearOff($interfaceName)) {
3886 my $code = <<END;
3887 static void initializeScriptWrappableForInterface(${implClassName}* object)
3888 {
3889 if (ScriptWrappable::wrapperCanBeStoredInObject(object))
3890 ScriptWrappable::setTypeInfoInObject(object, &${v8ClassName}::info);
3891 else
3892 ASSERT_NOT_REACHED();
3893 }
3894
3895 } // namespace WebCore
3896
3897 // In ScriptWrappable::init, the use of a local function declaration has an issu e on Windows:
3898 // the local declaration does not pick up the surrounding namespace. Therefore, we provide this function
3899 // in the global namespace.
3900 // (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/fe edback/details/664619/the-namespace-of-local-function-declarations-in-c)
3901 END
3902
3903 if (GetNamespaceForInterface($interface) eq "WebCore") {
3904 $code .= "void webCoreInitializeScriptWrappableForInterface(WebCore::${i mplClassName}* object)\n";
3905 } else {
3906 $code .= "void webCoreInitializeScriptWrappableForInterface(${implClassN ame}* object)\n";
3907 }
3908
3909 $code .= <<END;
3910 {
3911 WebCore::initializeScriptWrappableForInterface(object);
3912 }
3913
3914 namespace WebCore {
3915 END
3916 $implementation{nameSpaceWebCore}->addHeader($code);
3917 }
3918
3919 my $code = "WrapperTypeInfo ${v8ClassName}::info = { ${v8ClassName}::GetTemp late, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, ";
3920 $code .= "$rootForGC, ${v8ClassName}::installPerContextPrototypeProperties, $parentClassInfo, $WrapperTypePrototype };\n";
3921 $implementation{nameSpaceWebCore}->addHeader($code);
3922
3923 $implementation{nameSpaceInternal}->add("template <typename T> void V8_USE(T ) { }\n\n");
3924
3925 my $hasConstructors = 0;
3926 my $hasReplaceable = 0;
3927
3928 # Generate property accessors for attributes.
3929 for (my $index = 0; $index < @{$interface->attributes}; $index++) {
3930 my $attribute = @{$interface->attributes}[$index];
3931 my $attrType = $attribute->type;
3932 my $attrExt = $attribute->extendedAttributes;
3933
3934 # Generate special code for the constructor attributes.
3935 if ($attrType =~ /Constructor$/) {
3936 if (!HasCustomGetter($attrExt)) {
3937 $hasConstructors = 1;
3938 }
3939 next;
3940 }
3941
3942 if ($attrType eq "EventHandler" && $interfaceName eq "Window") {
3943 $attrExt->{"OnProto"} = 1;
3944 }
3945
3946 if ($attrType eq "SerializedScriptValue") {
3947 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
3948 }
3949
3950 GenerateNormalAttributeGetter($attribute, $interface, "");
3951 GenerateNormalAttributeGetterCallback($attribute, $interface, "");
3952 if ($attrExt->{"PerWorldBindings"}) {
3953 GenerateNormalAttributeGetter($attribute, $interface, "ForMainWorld" );
3954 GenerateNormalAttributeGetterCallback($attribute, $interface, "ForMa inWorld");
3955 }
3956 if (!HasCustomSetter($attrExt) && $attrExt->{"Replaceable"}) {
3957 $hasReplaceable = 1;
3958 } elsif (!IsReadonly($attribute)) {
3959 GenerateNormalAttributeSetter($attribute, $interface, "");
3960 GenerateNormalAttributeSetterCallback($attribute, $interface, "");
3961 if ($attrExt->{"PerWorldBindings"}) {
3962 GenerateNormalAttributeSetter($attribute, $interface, "ForMainWorl d");
3963 GenerateNormalAttributeSetterCallback($attribute, $interface, "For MainWorld");
3964 }
3965 }
3966 }
3967
3968 if ($hasConstructors) {
3969 GenerateConstructorGetter($interface);
3970 }
3971
3972 if ($hasConstructors || $hasReplaceable) {
3973 GenerateReplaceableAttributeSetter($interface);
3974 GenerateReplaceableAttributeSetterCallback($interface);
3975 }
3976
3977 if (NeedsOpaqueRootForGC($interface)) {
3978 GenerateOpaqueRootForGC($interface);
3979 }
3980
3981 if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne "Window") {
3982 GenerateSecurityCheckFunctions($interface);
3983 }
3984
3985 if (IsConstructorTemplate($interface, "TypedArray")) {
3986 my ($nativeType, $arrayType) = GetNativeTypeOfTypedArray($interface);
3987 $implementation{nameSpaceWebCore}->add(<<END);
3988 v8::Handle<v8::Object> wrap($implClassName* impl, v8::Handle<v8::Object> creatio nContext, v8::Isolate* isolate)
3989 {
3990 ASSERT(impl);
3991 v8::Handle<v8::Object> wrapper = ${v8ClassName}::createWrapper(impl, creatio nContext, isolate);
3992 if (!wrapper.IsEmpty())
3993 wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), $a rrayType, impl->length());
3994 return wrapper;
3995 }
3996
3997 END
3998 }
3999
4000 my @enabledPerContextFunctions;
4001 my @normalFunctions;
4002 my $needsDomainSafeFunctionSetter = 0;
4003 # Generate methods for functions.
4004 foreach my $function (@{$interface->functions}) {
4005 next if $function->name eq "";
4006 GenerateFunction($function, $interface, "");
4007 if ($function->extendedAttributes->{"PerWorldBindings"}) {
4008 GenerateFunction($function, $interface, "ForMainWorld");
4009 }
4010 if ($function->{overloadIndex} == @{$function->{overloads}}) {
4011 if ($function->{overloadIndex} > 1) {
4012 GenerateOverloadedFunction($function, $interface, "");
4013 if ($function->extendedAttributes->{"PerWorldBindings"}) {
4014 GenerateOverloadedFunction($function, $interface, "ForMainWo rld");
4015 }
4016 }
4017 GenerateFunctionCallback($function, $interface, "");
4018 if ($function->extendedAttributes->{"PerWorldBindings"}) {
4019 GenerateFunctionCallback($function, $interface, "ForMainWorld");
4020 }
4021 }
4022
4023 # If the function does not need domain security check, we need to
4024 # generate an access getter that returns different function objects
4025 # for different calling context.
4026 if ($interface->extendedAttributes->{"CheckSecurity"} && $function->exte ndedAttributes->{"DoNotCheckSecurity"}) {
4027 if (!HasCustomMethod($function->extendedAttributes) || $function->{o verloadIndex} == 1) {
4028 GenerateDomainSafeFunctionGetter($function, $interface);
4029 if (!$function->extendedAttributes->{"ReadOnly"}) {
4030 $needsDomainSafeFunctionSetter = 1;
4031 }
4032 }
4033 }
4034
4035 # Separate out functions that are enabled per context so we can process them specially.
4036 if ($function->extendedAttributes->{"EnabledPerContext"}) {
4037 push(@enabledPerContextFunctions, $function);
4038 } else {
4039 push(@normalFunctions, $function);
4040 }
4041 }
4042
4043 if ($needsDomainSafeFunctionSetter) {
4044 GenerateDomainSafeFunctionSetter($interface);
4045 }
4046
4047 # Attributes
4048 my $attributes = $interface->attributes;
4049
4050 # For the Window interface we partition the attributes into the
4051 # ones that disallows shadowing and the rest.
4052 my @disallowsShadowing;
4053 # Also separate out attributes that are enabled at runtime so we can process them specially.
4054 my @enabledAtRuntimeAttributes;
4055 my @enabledPerContextAttributes;
4056 my @normalAttributes;
4057 foreach my $attribute (@$attributes) {
4058
4059 if ($interfaceName eq "Window" && $attribute->extendedAttributes->{"Unfo rgeable"}) {
4060 push(@disallowsShadowing, $attribute);
4061 } elsif ($attribute->extendedAttributes->{"EnabledAtRuntime"} || $attrib ute->extendedAttributes->{"EnabledPerContext"}) {
4062 if ($attribute->extendedAttributes->{"EnabledPerContext"}) {
4063 push(@enabledPerContextAttributes, $attribute);
4064 }
4065 if ($attribute->extendedAttributes->{"EnabledAtRuntime"}) {
4066 push(@enabledAtRuntimeAttributes, $attribute);
4067 }
4068 } else {
4069 push(@normalAttributes, $attribute);
4070 }
4071 }
4072 AddToImplIncludes("bindings/v8/V8DOMConfiguration.h");
4073 $attributes = \@normalAttributes;
4074 # Put the attributes that disallow shadowing on the shadow object.
4075 if (@disallowsShadowing) {
4076 my $code = "";
4077 $code .= "static const V8DOMConfiguration::AttributeConfiguration shadow Attributes[] = {\n";
4078 $code .= GenerateAttributeConfigurationArray($interface, \@disallowsShad owing);
4079 $code .= "};\n\n";
4080 $implementation{nameSpaceWebCore}->add($code);
4081 }
4082
4083 my $has_attributes = 0;
4084 if (@$attributes) {
4085 $has_attributes = 1;
4086 my $code = "";
4087 $code .= "static const V8DOMConfiguration::AttributeConfiguration ${v8Cl assName}Attributes[] = {\n";
4088 $code .= GenerateAttributeConfigurationArray($interface, $attributes);
4089 $code .= "};\n\n";
4090 $implementation{nameSpaceWebCore}->add($code);
4091 }
4092
4093 # Setup table of standard callback functions
4094 my $num_callbacks = 0;
4095 my $has_callbacks = 0;
4096 $code = "";
4097 foreach my $function (@normalFunctions) {
4098 # Only one table entry is needed for overloaded methods:
4099 next if $function->{overloadIndex} > 1;
4100 # Don't put any nonstandard functions into this table:
4101 next if !IsStandardFunction($interface, $function);
4102 next if $function->name eq "";
4103 if (!$has_callbacks) {
4104 $has_callbacks = 1;
4105 $code .= "static const V8DOMConfiguration::MethodConfiguration ${v8C lassName}Methods[] = {\n";
4106 }
4107 my $name = $function->name;
4108 my $methodForMainWorld = "0";
4109 if ($function->extendedAttributes->{"PerWorldBindings"}) {
4110 $methodForMainWorld = "${implClassName}V8Internal::${name}MethodCall backForMainWorld";
4111 }
4112 my $functionLength = GetFunctionLength($function);
4113 my $conditionalString = GenerateConditionalString($function);
4114 $code .= "#if ${conditionalString}\n" if $conditionalString;
4115 $code .= <<END;
4116 {"$name", ${implClassName}V8Internal::${name}MethodCallback, ${methodForMain World}, ${functionLength}},
4117 END
4118 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4119 $num_callbacks++;
4120 }
4121 $code .= "};\n\n" if $has_callbacks;
4122 $implementation{nameSpaceWebCore}->add($code);
4123
4124 my $has_constants = 0;
4125 if (@{$interface->constants}) {
4126 $has_constants = 1;
4127 }
4128
4129 if (!HasCustomConstructor($interface)) {
4130 if ($interface->extendedAttributes->{"NamedConstructor"}) {
4131 GenerateNamedConstructor(@{$interface->constructors}[0], $interface) ;
4132 } elsif ($interface->extendedAttributes->{"Constructor"}) {
4133 GenerateConstructor($interface);
4134 } elsif (IsConstructorTemplate($interface, "Event")) {
4135 GenerateEventConstructor($interface);
4136 }
4137 }
4138 if (IsConstructable($interface)) {
4139 GenerateConstructorCallback($interface);
4140 }
4141
4142 my $access_check = "";
4143 if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne " Window") {
4144 $access_check = "instance->SetAccessCheckCallbacks(${implClassName}V8Int ernal::namedSecurityCheck, ${implClassName}V8Internal::indexedSecurityCheck, v8: :External::New(&${v8ClassName}::info));";
4145 }
4146
4147 # For the Window interface, generate the shadow object template
4148 # configuration method.
4149 if ($interfaceName eq "Window") {
4150 $implementation{nameSpaceWebCore}->add(<<END);
4151 static void ConfigureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ, v8::Isolate* isolate, WrapperWorldType currentWorldType)
4152 {
4153 V8DOMConfiguration::installAttributes(templ, v8::Handle<v8::ObjectTemplate>( ), shadowAttributes, WTF_ARRAY_LENGTH(shadowAttributes), isolate, currentWorldTy pe);
4154
4155 // Install a security handler with V8.
4156 templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window: :indexedSecurityCheckCustom, v8::External::New(&V8Window::info));
4157 templ->SetInternalFieldCount(V8Window::internalFieldCount);
4158 }
4159 END
4160 }
4161
4162 if (!$parentClassTemplate) {
4163 $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()";
4164 }
4165
4166 # Generate the template configuration method
4167 $code = <<END;
4168 static v8::Handle<v8::FunctionTemplate> Configure${v8ClassName}Template(v8::Hand le<v8::FunctionTemplate> desc, v8::Isolate* isolate, WrapperWorldType currentWor ldType)
4169 {
4170 desc->ReadOnlyPrototype();
4171
4172 v8::Local<v8::Signature> defaultSignature;
4173 END
4174 if ($interface->extendedAttributes->{"EnabledAtRuntime"}) {
4175 my $enable_function = GetRuntimeEnableFunctionName($interface);
4176 $code .= <<END;
4177 if (!${enable_function}())
4178 defaultSignature = V8DOMConfiguration::installDOMClassTemplate(desc, \"\ ", $parentClassTemplate, ${v8ClassName}::internalFieldCount, 0, 0, 0, 0, isolate , currentWorldType);
4179 else
4180 END
4181 }
4182 $code .= <<END;
4183 defaultSignature = V8DOMConfiguration::installDOMClassTemplate(desc, \"${int erfaceName}\", $parentClassTemplate, ${v8ClassName}::internalFieldCount,
4184 END
4185 # Set up our attributes if we have them
4186 if ($has_attributes) {
4187 $code .= <<END;
4188 ${v8ClassName}Attributes, WTF_ARRAY_LENGTH(${v8ClassName}Attributes),
4189 END
4190 } else {
4191 $code .= <<END;
4192 0, 0,
4193 END
4194 }
4195
4196 if ($has_callbacks) {
4197 $code .= <<END;
4198 ${v8ClassName}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods), isolate, currentWorldType);
4199 END
4200 } else {
4201 $code .= <<END;
4202 0, 0, isolate, currentWorldType);
4203 END
4204 }
4205
4206 AddToImplIncludes("wtf/UnusedParam.h");
4207 $code .= <<END;
4208 UNUSED_PARAM(defaultSignature);
4209 END
4210
4211 if (IsConstructable($interface)) {
4212 $code .= " desc->SetCallHandler(${v8ClassName}::constructorCallback); \n";
4213 my $interfaceLength = GetInterfaceLength($interface);
4214 $code .= " desc->SetLength(${interfaceLength});\n";
4215 }
4216
4217 if ($access_check or @enabledAtRuntimeAttributes or @normalFunctions or $has _constants) {
4218 $code .= <<END;
4219 v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate();
4220 v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate();
4221 UNUSED_PARAM(instance);
4222 UNUSED_PARAM(proto);
4223 END
4224 }
4225
4226 if ($access_check) {
4227 $code .= " $access_check\n";
4228 }
4229
4230 # Setup the enable-at-runtime attributes if we have them
4231 foreach my $runtime_attr (@enabledAtRuntimeAttributes) {
4232 next if grep { $_ eq $runtime_attr } @enabledPerContextAttributes;
4233 my $enable_function = GetRuntimeEnableFunctionName($runtime_attr);
4234 my $conditionalString = GenerateConditionalString($runtime_attr);
4235 $code .= "\n#if ${conditionalString}\n" if $conditionalString;
4236 $code .= " if (${enable_function}()) {\n";
4237 $code .= " static const V8DOMConfiguration::AttributeConfiguratio n attributeConfiguration =\\\n";
4238 $code .= GenerateAttributeConfiguration($interface, $runtime_attr, ";", " ");
4239 $code .= <<END;
4240 V8DOMConfiguration::installAttribute(instance, proto, attributeConfigura tion, isolate, currentWorldType);
4241 }
4242 END
4243 $code .= "\n#endif // ${conditionalString}\n" if $conditionalString;
4244 }
4245
4246 my @constantsEnabledAtRuntime;
4247 if ($has_constants) {
4248 $code .= " static const V8DOMConfiguration::ConstantConfiguration ${v 8ClassName}Constants[] = {\n";
4249 foreach my $constant (@{$interface->constants}) {
4250 my $name = $constant->name;
4251 my $value = $constant->value;
4252 my $attrExt = $constant->extendedAttributes;
4253 my $implementedBy = $attrExt->{"ImplementedBy"};
4254 if ($implementedBy) {
4255 my $implementedByImplName = GetImplNameFromImplementedBy($implem entedBy);
4256 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $imple mentedByImplName));
4257 }
4258 if ($attrExt->{"EnabledAtRuntime"}) {
4259 push(@constantsEnabledAtRuntime, $constant);
4260 } else {
4261 $code .= <<END;
4262 {"${name}", $value},
4263 END
4264 }
4265 }
4266 $code .= " };\n";
4267 $code .= <<END;
4268 V8DOMConfiguration::installConstants(desc, proto, ${v8ClassName}Constants, W TF_ARRAY_LENGTH(${v8ClassName}Constants), isolate);
4269 END
4270 # Setup the enable-at-runtime constants if we have them
4271 foreach my $runtime_const (@constantsEnabledAtRuntime) {
4272 my $enable_function = GetRuntimeEnableFunctionName($runtime_const);
4273 my $name = $runtime_const->name;
4274 my $value = $runtime_const->value;
4275 $code .= " if (${enable_function}()) {\n";
4276 $code .= <<END;
4277 static const V8DOMConfiguration::ConstantConfiguration constantConfigura tion = {"${name}", static_cast<signed int>(${value})};
4278 V8DOMConfiguration::installConstants(desc, proto, &constantConfiguration , 1, isolate);
4279 END
4280 $code .= " }\n";
4281 }
4282 $code .= join "", GenerateCompileTimeCheckForEnumsIfNeeded($interface);
4283 }
4284
4285 $code .= GenerateImplementationIndexedPropertyAccessors($interface);
4286 $code .= GenerateImplementationNamedPropertyAccessors($interface);
4287 $code .= GenerateImplementationLegacyCall($interface);
4288 $code .= GenerateImplementationMasqueradesAsUndefined($interface);
4289
4290 # Define our functions with Set() or SetAccessor()
4291 my $total_functions = 0;
4292 foreach my $function (@normalFunctions) {
4293 # Only one accessor is needed for overloaded methods:
4294 next if $function->{overloadIndex} > 1;
4295 next if $function->name eq "";
4296
4297 $total_functions++;
4298 next if IsStandardFunction($interface, $function);
4299 $code .= GenerateNonStandardFunction($interface, $function);
4300 $num_callbacks++;
4301 }
4302
4303 die "Wrong number of callbacks generated for $interfaceName ($num_callbacks, should be $total_functions)" if $num_callbacks != $total_functions;
4304
4305 # Special cases
4306 if ($interfaceName eq "Window") {
4307 $code .= <<END;
4308
4309 proto->SetInternalFieldCount(V8Window::internalFieldCount);
4310 desc->SetHiddenPrototype(true);
4311 instance->SetInternalFieldCount(V8Window::internalFieldCount);
4312 // Set access check callbacks, but turned off initially.
4313 // When a context is detached from a frame, turn on the access check.
4314 // Turning on checks also invalidates inline caches of the object.
4315 instance->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Wind ow::indexedSecurityCheckCustom, v8::External::New(&V8Window::info), false);
4316 END
4317 }
4318 if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGl obalScope" or $interfaceName eq "SharedWorkerGlobalScope") {
4319 $code .= <<END;
4320 desc->SetHiddenPrototype(true);
4321 END
4322 }
4323
4324 $code .= <<END;
4325
4326 // Custom toString template
4327 desc->Set(v8::String::NewSymbol("toString"), V8PerIsolateData::current()->to StringTemplate());
4328 return desc;
4329 }
4330
4331 END
4332 $implementation{nameSpaceWebCore}->add($code);
4333
4334 $implementation{nameSpaceWebCore}->add(<<END);
4335 v8::Handle<v8::FunctionTemplate> ${v8ClassName}::GetTemplate(v8::Isolate* isolat e, WrapperWorldType currentWorldType)
4336 {
4337 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
4338 V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWo rldType).find(&info);
4339 if (result != data->templateMap(currentWorldType).end())
4340 return result->value.newLocal(isolate);
4341
4342 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4343 v8::HandleScope handleScope(isolate);
4344 v8::Handle<v8::FunctionTemplate> templ =
4345 Configure${v8ClassName}Template(data->rawTemplate(&info, currentWorldTyp e), isolate, currentWorldType);
4346 data->templateMap(currentWorldType).add(&info, UnsafePersistent<v8::Function Template>(isolate, templ));
4347 return handleScope.Close(templ);
4348 }
4349
4350 END
4351 $implementation{nameSpaceWebCore}->add(<<END);
4352 bool ${v8ClassName}::HasInstance(v8::Handle<v8::Value> value, v8::Isolate* isola te, WrapperWorldType currentWorldType)
4353 {
4354 return V8PerIsolateData::from(isolate)->hasInstance(&info, value, currentWor ldType);
4355 }
4356
4357 END
4358 $implementation{nameSpaceWebCore}->add(<<END);
4359 bool ${v8ClassName}::HasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isol ate* isolate)
4360 {
4361 return V8PerIsolateData::from(isolate)->hasInstance(&info, value, MainWorld)
4362 || V8PerIsolateData::from(isolate)->hasInstance(&info, value, IsolatedWo rld)
4363 || V8PerIsolateData::from(isolate)->hasInstance(&info, value, WorkerWorl d);
4364 }
4365
4366 END
4367
4368 if (@enabledPerContextAttributes) {
4369 my $code = "";
4370 $code .= <<END;
4371 void ${v8ClassName}::installPerContextProperties(v8::Handle<v8::Object> instance , ${nativeType}* impl, v8::Isolate* isolate)
4372 {
4373 v8::Local<v8::Object> proto = v8::Local<v8::Object>::Cast(instance->GetProto type());
4374 END
4375
4376 # Setup the enable-by-settings attributes if we have them
4377 foreach my $runtimeAttribute (@enabledPerContextAttributes) {
4378 my $enableFunction = GetContextEnableFunction($runtimeAttribute);
4379 my $conditionalString = GenerateConditionalString($runtimeAttribute) ;
4380 $code .= "\n#if ${conditionalString}\n" if $conditionalString;
4381 if (grep { $_ eq $runtimeAttribute } @enabledAtRuntimeAttributes) {
4382 my $runtimeEnableFunction = GetRuntimeEnableFunctionName($runtim eAttribute);
4383 $code .= " if (${enableFunction}(impl->document()) && ${runti meEnableFunction}()) {\n";
4384 } else {
4385 $code .= " if (${enableFunction}(impl->document())) {\n";
4386 }
4387
4388 $code .= " static const V8DOMConfiguration::AttributeConfigur ation attributeConfiguration =\\\n";
4389 $code .= GenerateAttributeConfiguration($interface, $runtimeAttribut e, ";", " ");
4390 $code .= <<END;
4391 V8DOMConfiguration::installAttribute(instance, proto, attributeConfigura tion, isolate);
4392 END
4393 $code .= " }\n";
4394 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4395 }
4396 $code .= <<END;
4397 }
4398
4399 END
4400 $implementation{nameSpaceWebCore}->add($code);
4401 }
4402
4403 if (@enabledPerContextFunctions) {
4404 my $code = "";
4405 $code .= <<END;
4406 void ${v8ClassName}::installPerContextPrototypeProperties(v8::Handle<v8::Object> proto, v8::Isolate* isolate)
4407 {
4408 UNUSED_PARAM(proto);
4409 END
4410 # Setup the enable-by-settings functions if we have them
4411 $code .= <<END;
4412 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(GetTemplate(i solate, worldType(isolate)));
4413 UNUSED_PARAM(defaultSignature);
4414
4415 ScriptExecutionContext* context = toScriptExecutionContext(proto->CreationCo ntext());
4416 END
4417
4418 foreach my $runtimeFunc (@enabledPerContextFunctions) {
4419 my $enableFunction = GetContextEnableFunction($runtimeFunc);
4420 my $functionLength = GetFunctionLength($runtimeFunc);
4421 my $conditionalString = GenerateConditionalString($runtimeFunc);
4422 $code .= "\n#if ${conditionalString}\n" if $conditionalString;
4423 $code .= " if (context && context->isDocument() && ${enableFuncti on}(toDocument(context)))\n";
4424 my $name = $runtimeFunc->name;
4425 $code .= <<END;
4426 proto->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New($ {implClassName}V8Internal::${name}MethodCallback, v8Undefined(), defaultSignatur e, $functionLength)->GetFunction());
4427 END
4428 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
4429 }
4430
4431 $code .= <<END;
4432 }
4433
4434 END
4435 $implementation{nameSpaceWebCore}->add($code);
4436 }
4437
4438 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
4439 # MessagePort is handled like an active dom object even though it doesn' t inherit
4440 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject.
4441 my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(obje ct)";
4442 $implementation{nameSpaceWebCore}->add(<<END);
4443 ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> object )
4444 {
4445 return $returnValue;
4446 }
4447
4448 END
4449 }
4450
4451 if (InheritsInterface($interface, "EventTarget")) {
4452 $implementation{nameSpaceWebCore}->add(<<END);
4453 EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object)
4454 {
4455 return toNative(object);
4456 }
4457
4458 END
4459 }
4460
4461 if ($interfaceName eq "Window") {
4462 $implementation{nameSpaceWebCore}->add(<<END);
4463 v8::Handle<v8::ObjectTemplate> V8Window::GetShadowObjectTemplate(v8::Isolate* is olate, WrapperWorldType currentWorldType)
4464 {
4465 if (currentWorldType == MainWorld) {
4466 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowOb jectCacheForMainWorld, ());
4467 if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) {
4468 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4469 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
4470 ConfigureShadowObjectTemplate(templ, isolate, currentWorldType);
4471 V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ);
4472 return templ;
4473 }
4474 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectC acheForMainWorld);
4475 } else {
4476 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowOb jectCacheForNonMainWorld, ());
4477 if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) {
4478 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
4479 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
4480 ConfigureShadowObjectTemplate(templ, isolate, currentWorldType);
4481 V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ);
4482 return templ;
4483 }
4484 return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectC acheForNonMainWorld);
4485 }
4486 }
4487
4488 END
4489 }
4490
4491 GenerateToV8Converters($interface, $v8ClassName, $nativeType);
4492
4493 $implementation{nameSpaceWebCore}->add(<<END);
4494 void ${v8ClassName}::derefObject(void* object)
4495 {
4496 fromInternalPointer(object)->deref();
4497 }
4498
4499 END
4500 }
4501
4502 sub GenerateHeaderContentHeader
4503 {
4504 my $interface = shift;
4505 my $v8ClassName = GetV8ClassName($interface);
4506 my $conditionalString = GenerateConditionalString($interface);
4507
4508 my @headerContentHeader = split("\r", $headerTemplate);
4509
4510 push(@headerContentHeader, "\n#ifndef ${v8ClassName}" . "_h\n");
4511 push(@headerContentHeader, "#define ${v8ClassName}" . "_h\n\n");
4512 push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalStri ng;
4513 return join "", @headerContentHeader;
4514 }
4515
4516 sub GenerateCallbackHeader
4517 {
4518 my $object = shift;
4519 my $interface = shift;
4520
4521 my $interfaceName = $interface->name;
4522 my $implClassName = GetImplName($interface);
4523 my $v8ClassName = GetV8ClassName($interface);
4524
4525 $header{root}->addFooter("\n");
4526
4527 my @includes = ();
4528 push(@includes, "bindings/v8/ActiveDOMCallback.h");
4529 push(@includes, "bindings/v8/DOMWrapperWorld.h");
4530 push(@includes, "bindings/v8/ScopedPersistent.h");
4531 push(@includes, HeaderFilesForInterface($interfaceName, $implClassName));
4532 for my $include (sort @includes) {
4533 $header{includes}->add("#include \"$include\"\n");
4534 }
4535 $header{nameSpaceWebCore}->addHeader("\nclass ScriptExecutionContext;\n\n");
4536 $header{class}->addHeader("class $v8ClassName : public $implClassName, publi c ActiveDOMCallback {");
4537 $header{class}->addFooter("};\n");
4538
4539 $header{classPublic}->add(<<END);
4540 static PassRefPtr<${v8ClassName}> create(v8::Handle<v8::Value> value, Script ExecutionContext* context)
4541 {
4542 ASSERT(value->IsObject());
4543 ASSERT(context);
4544 return adoptRef(new ${v8ClassName}(v8::Handle<v8::Object>::Cast(value), context));
4545 }
4546
4547 virtual ~${v8ClassName}();
4548
4549 END
4550
4551 # Functions
4552 my $numFunctions = @{$interface->functions};
4553 if ($numFunctions > 0) {
4554 $header{classPublic}->add(" // Functions\n");
4555 foreach my $function (@{$interface->functions}) {
4556 my $code = " virtual " . GetNativeTypeForCallbacks($function->typ e) . " " . $function->name . "(";
4557
4558 my @args = ();
4559 if (ExtendedAttributeContains($function->extendedAttributes->{"CallW ith"}, "ThisValue")) {
4560 push(@args, GetNativeType("any") . " thisValue");
4561 }
4562 my @params = @{$function->parameters};
4563 foreach my $param (@params) {
4564 push(@args, GetNativeTypeForCallbacks($param->type) . " " . $par am->name);
4565 }
4566 $code .= join(", ", @args);
4567 $code .= ");\n";
4568 $header{classPublic}->add($code);
4569 }
4570 }
4571
4572 $header{classPublic}->add(<<END);
4573
4574 virtual ScriptExecutionContext* scriptExecutionContext() const { return Cont extLifecycleObserver::scriptExecutionContext(); }
4575
4576 END
4577 $header{classPrivate}->add(<<END);
4578 ${v8ClassName}(v8::Handle<v8::Object>, ScriptExecutionContext*);
4579
4580 ScopedPersistent<v8::Object> m_callback;
4581 RefPtr<DOMWrapperWorld> m_world;
4582 END
4583 }
4584
4585 sub GenerateCallbackImplementation
4586 {
4587 my $object = shift;
4588 my $interface = shift;
4589 my $v8ClassName = GetV8ClassName($interface);
4590
4591 AddToImplIncludes("core/dom/ScriptExecutionContext.h");
4592 AddToImplIncludes("bindings/v8/V8Binding.h");
4593 AddToImplIncludes("bindings/v8/V8Callback.h");
4594 AddToImplIncludes("wtf/Assertions.h");
4595
4596 $implementation{nameSpaceWebCore}->add(<<END);
4597 ${v8ClassName}::${v8ClassName}(v8::Handle<v8::Object> callback, ScriptExecutionC ontext* context)
4598 : ActiveDOMCallback(context)
4599 , m_callback(toIsolate(context), callback)
4600 , m_world(DOMWrapperWorld::current())
4601 {
4602 }
4603
4604 END
4605
4606 $implementation{nameSpaceWebCore}->add(<<END);
4607 ${v8ClassName}::~${v8ClassName}()
4608 {
4609 }
4610
4611 END
4612
4613 # Functions
4614 my $numFunctions = @{$interface->functions};
4615 if ($numFunctions > 0) {
4616 $implementation{nameSpaceWebCore}->add("// Functions\n");
4617 foreach my $function (@{$interface->functions}) {
4618 my $code = "";
4619 my @params = @{$function->parameters};
4620 next if $function->extendedAttributes->{"Custom"};
4621
4622 AddIncludesForType($function->type);
4623 die "We don't yet support callbacks that return non-boolean values.\ n" if $function->type ne "boolean";
4624 $code .= "\n" . GetNativeTypeForCallbacks($function->type) . " ${v8C lassName}::" . $function->name . "(";
4625 my $callWithThisValue = ExtendedAttributeContains($function->extende dAttributes->{"CallWith"}, "ThisValue");
4626
4627 my @args = ();
4628 if ($callWithThisValue) {
4629 push(@args, GetNativeTypeForCallbacks("any") . " thisValue");
4630 }
4631 foreach my $param (@params) {
4632 my $paramName = $param->name;
4633 my $type = $param->type;
4634 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
4635
4636 if ($arrayOrSequenceType) {
4637 if (IsRefPtrType($arrayOrSequenceType)) {
4638 AddIncludesForType($arrayOrSequenceType);
4639 }
4640 } else {
4641 AddIncludesForType($type);
4642 }
4643
4644 push(@args, GetNativeTypeForCallbacks($type) . " " . $paramName) ;
4645 }
4646 $code .= join(", ", @args);
4647
4648 $code .= ")\n";
4649 $code .= "{\n";
4650 $code .= " if (!canInvokeCallback())\n";
4651 $code .= " return true;\n\n";
4652 $code .= " v8::Isolate* isolate = v8::Isolate::GetCurrent();\n";
4653 $code .= " v8::HandleScope handleScope(isolate);\n\n";
4654 $code .= " v8::Handle<v8::Context> v8Context = toV8Context(script ExecutionContext(), m_world.get());\n";
4655 $code .= " if (v8Context.IsEmpty())\n";
4656 $code .= " return true;\n\n";
4657 $code .= " v8::Context::Scope scope(v8Context);\n\n";
4658
4659 my $thisObjectHandle = "";
4660 if ($callWithThisValue) {
4661 $code .= " v8::Handle<v8::Value> thisHandle = thisValue.v8Val ue();\n";
4662 $code .= " if (thisHandle.IsEmpty()) {\n";
4663 $code .= " if (!isScriptControllerTerminating())\n";
4664 $code .= " CRASH();\n";
4665 $code .= " return true;\n";
4666 $code .= " }\n";
4667 $code .= " ASSERT(thisHandle->isObject());\n";
4668 $thisObjectHandle = "v8::Handle<v8::Object>::Cast(thisHandle), " ;
4669 }
4670 @args = ();
4671 foreach my $param (@params) {
4672 my $paramName = $param->name;
4673 $code .= NativeToJSValue($param->type, $param->extendedAttribute s, $paramName, " ", "v8::Handle<v8::Value> ${paramName}Handle =", "v8::Handle <v8::Object>()", "isolate", "") . "\n";
4674 $code .= " if (${paramName}Handle.IsEmpty()) {\n";
4675 $code .= " if (!isScriptControllerTerminating())\n";
4676 $code .= " CRASH();\n";
4677 $code .= " return true;\n";
4678 $code .= " }\n";
4679 push(@args, " ${paramName}Handle");
4680 }
4681
4682 if (scalar(@args) > 0) {
4683 $code .= "\n v8::Handle<v8::Value> argv[] = {\n";
4684 $code .= join(",\n", @args);
4685 $code .= "\n };\n\n";
4686 } else {
4687 $code .= "\n v8::Handle<v8::Value> *argv = 0;\n\n";
4688 }
4689 $code .= " bool callbackReturnValue = false;\n";
4690 $code .= " return !invokeCallback(m_callback.newLocal(isolate), $ {thisObjectHandle}" . scalar(@args) . ", argv, callbackReturnValue, scriptExecut ionContext(), isolate);\n";
4691 $code .= "}\n";
4692 $implementation{nameSpaceWebCore}->add($code);
4693 }
4694 }
4695 }
4696
4697 sub BaseInterfaceName
4698 {
4699 my $interface = shift;
4700
4701 while ($interface->parent) {
4702 $interface = ParseInterface($interface->parent);
4703 }
4704
4705 return $interface->name;
4706 }
4707
4708 sub GenerateToV8Converters
4709 {
4710 my $interface = shift;
4711 my $v8ClassName = shift;
4712 my $nativeType = shift;
4713 my $interfaceName = $interface->name;
4714
4715 if ($interface->extendedAttributes->{"DoNotGenerateWrap"} || $interface->ext endedAttributes->{"DoNotGenerateToV8"}) {
4716 return;
4717 }
4718
4719 AddToImplIncludes("bindings/v8/ScriptController.h");
4720
4721 my $createWrapperArgumentType = GetPassRefPtrType($nativeType);
4722 my $baseType = BaseInterfaceName($interface);
4723
4724 # FIXME: Do we really need to treat "GenerateIsReachable", "CustomIsReachabl e" and /SVG/
4725 # as dependent DOM objects?
4726 my $wrapperConfiguration = "WrapperConfiguration::Independent";
4727 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")
4728 || InheritsExtendedAttribute($interface, "DependentLifetime")
4729 || InheritsExtendedAttribute($interface, "GenerateIsReachable")
4730 || InheritsExtendedAttribute($interface, "CustomIsReachable")
4731 || $v8ClassName =~ /SVG/) {
4732 $wrapperConfiguration = "WrapperConfiguration::Dependent";
4733 }
4734
4735 my $code = "";
4736 $code .= <<END;
4737 v8::Handle<v8::Object> ${v8ClassName}::createWrapper(${createWrapperArgumentType } impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
4738 {
4739 ASSERT(impl.get());
4740 ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl.get(), isolate));
4741 if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) {
4742 const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObje ct(impl.get());
4743 // Might be a XXXConstructor::info instead of an XXX::info. These will b oth have
4744 // the same object de-ref functions, though, so use that as the basis of the check.
4745 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == info.derefObjectFunction);
4746 }
4747
4748 END
4749
4750 $code .= <<END if ($baseType ne $interfaceName);
4751 END
4752
4753 if (InheritsInterface($interface, "Document")) {
4754 AddToImplIncludes("core/page/Frame.h");
4755 $code .= <<END;
4756 if (Frame* frame = impl->frame()) {
4757 if (frame->script()->initializeMainWorld()) {
4758 // initializeMainWorld may have created a wrapper for the object, re try from the start.
4759 v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper<${v8ClassN ame}>(impl.get(), isolate);
4760 if (!wrapper.IsEmpty())
4761 return wrapper;
4762 }
4763 }
4764 END
4765 }
4766
4767 $code .= <<END;
4768 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext , &info, toInternalPointer(impl.get()), isolate);
4769 if (UNLIKELY(wrapper.IsEmpty()))
4770 return wrapper;
4771
4772 END
4773 if (IsTypedArrayType($interface->name)) {
4774 AddToImplIncludes("bindings/v8/custom/V8ArrayBufferCustom.h");
4775 $code .= <<END;
4776 if (!impl->buffer()->hasDeallocationObserver()) {
4777 v8::V8::AdjustAmountOfExternalAllocatedMemory(impl->buffer()->byteLength ());
4778 impl->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserve r::instance());
4779 }
4780 END
4781 }
4782
4783 if (InheritsInterface($interface, "AudioBuffer")) {
4784 AddToImplIncludes("modules/webaudio/AudioBuffer.h");
4785 $code .= <<END;
4786 for (unsigned i = 0, n = impl->numberOfChannels(); i < n; i++) {
4787 Float32Array* channelData = impl->getChannelData(i);
4788 if (!channelData->buffer()->hasDeallocationObserver()) {
4789 v8::V8::AdjustAmountOfExternalAllocatedMemory(channelData->buffer()- >byteLength());
4790 channelData->buffer()->setDeallocationObserver(V8ArrayBufferDealloca tionObserver::instance());
4791 }
4792 }
4793 END
4794 }
4795
4796
4797 $code .= <<END;
4798 installPerContextProperties(wrapper, impl.get(), isolate);
4799 V8DOMWrapper::associateObjectWithWrapper<$v8ClassName>(impl, &info, wrapper, isolate, $wrapperConfiguration);
4800 return wrapper;
4801 }
4802
4803 END
4804 $implementation{nameSpaceWebCore}->add($code);
4805 }
4806
4807 sub GenerateSecurityCheckFunctions
4808 {
4809 my $interface = shift;
4810 my $implClassName = GetImplName($interface);
4811 my $v8ClassName = GetV8ClassName($interface);
4812
4813 AddToImplIncludes("bindings/v8/BindingSecurity.h");
4814 $implementation{nameSpaceInternal}->add(<<END);
4815 bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::Access Type type, v8::Local<v8::Value>)
4816 {
4817 $implClassName* imp = ${v8ClassName}::toNative(host);
4818 return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSe curityError);
4819 }
4820
4821 END
4822 $implementation{nameSpaceInternal}->add(<<END);
4823 bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8 ::AccessType type, v8::Local<v8::Value>)
4824 {
4825 $implClassName* imp = ${v8ClassName}::toNative(host);
4826 return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSe curityError);
4827 }
4828
4829 END
4830 }
4831
4832 sub GetNativeTypeForConversions
4833 {
4834 my $interface = shift;
4835 my $implClassName = GetImplName($interface);
4836 $implClassName = GetSVGTypeNeedingTearOff($interface->name) if IsSVGTypeNeed ingTearOff($interface->name);
4837 return $implClassName;
4838 }
4839
4840 sub GetNamespaceForInterface
4841 {
4842 my $interface = shift;
4843 return "WTF" if IsTypedArrayType($interface->name);
4844 return "WebCore";
4845 }
4846
4847 sub GenerateFunctionCallString
4848 {
4849 my $function = shift;
4850 my $numberOfParameters = shift;
4851 my $indent = shift;
4852 my $interface = shift;
4853 my $forMainWorldSuffix = shift;
4854 my %replacements = @_;
4855
4856 my $interfaceName = $interface->name;
4857 my $implClassName = GetImplName($interface);
4858 my $name = GetImplName($function);
4859 my $returnType = $function->type;
4860 my $nativeReturnType = GetNativeType($returnType, {}, "");
4861 my $code = "";
4862
4863 my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interf aceName =~ /List$/);
4864 $nativeReturnType = GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTe arOffType;
4865
4866 my $index = 0;
4867
4868 my @arguments;
4869 my $functionName;
4870 my $implementedBy = $function->extendedAttributes->{"ImplementedBy"};
4871 if ($implementedBy) {
4872 my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy) ;
4873 AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedBy ImplName));
4874 unshift(@arguments, "imp") if !$function->isStatic;
4875 $functionName = "${implementedByImplName}::${name}";
4876 } elsif ($function->isStatic) {
4877 $functionName = "${implClassName}::${name}";
4878 } else {
4879 $functionName = "imp->${name}";
4880 }
4881
4882 my $callWith = $function->extendedAttributes->{"CallWith"};
4883 my ($callWithArgs, $subCode) = GenerateCallWith($callWith, $indent, 1, $func tion);
4884 $code .= $subCode;
4885 unshift(@arguments, @$callWithArgs);
4886 $index += @$callWithArgs;
4887 $numberOfParameters += @$callWithArgs;
4888
4889 foreach my $parameter (@{$function->parameters}) {
4890 if ($index eq $numberOfParameters) {
4891 last;
4892 }
4893 my $paramName = $parameter->name;
4894 my $paramType = $parameter->type;
4895
4896 if ($replacements{$paramName}) {
4897 push @arguments, $replacements{$paramName};
4898 } elsif ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathN SResolver") {
4899 push @arguments, "$paramName.get()";
4900 } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceNam e =~ /List$/) {
4901 AddToImplIncludes("core/dom/ExceptionCode.h");
4902 push @arguments, "$paramName->propertyReference()";
4903 $code .= $indent . "if (!$paramName) {\n";
4904 $code .= $indent . " setDOMException(WebCore::TypeMismatchError, args.GetIsolate());\n";
4905 $code .= $indent . " return;\n";
4906 $code .= $indent . "}\n";
4907 } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTrans formList") {
4908 push @arguments, "$paramName.get()";
4909 } else {
4910 push @arguments, $paramName;
4911 }
4912 $index++;
4913 }
4914
4915 if ($function->extendedAttributes->{"RaisesException"}) {
4916 push @arguments, "es";
4917 }
4918
4919 my $functionString = "$functionName(" . join(", ", @arguments) . ")";
4920
4921 my $return = "result";
4922 my $returnIsRef = IsRefPtrType($returnType);
4923
4924 if ($returnType eq "void") {
4925 $code .= $indent . "$functionString;\n";
4926 } elsif (ExtendedAttributeContains($callWith, "ScriptState") or $function->e xtendedAttributes->{"RaisesException"}) {
4927 $code .= $indent . $nativeReturnType . " result = $functionString;\n";
4928 } else {
4929 # Can inline the function call into the return statement to avoid overhe ad of using a Ref<> temporary
4930 $return = $functionString;
4931 $returnIsRef = 0;
4932
4933 if ($interfaceName eq "SVGTransformList" and IsRefPtrType($returnType)) {
4934 $return = "WTF::getPtr(" . $return . ")";
4935 }
4936 }
4937
4938 if ($function->extendedAttributes->{"RaisesException"}) {
4939 $code .= $indent . "if (es.throwIfNeeded())\n";
4940 $code .= $indent . " return;\n";
4941 }
4942
4943 if (ExtendedAttributeContains($callWith, "ScriptState")) {
4944 $code .= $indent . "if (state.hadException()) {\n";
4945 $code .= $indent . " v8::Local<v8::Value> exception = state.exception ();\n";
4946 $code .= $indent . " state.clearException();\n";
4947 $code .= $indent . " throwError(exception, args.GetIsolate());\n";
4948 $code .= $indent . " return;\n";
4949 $code .= $indent . "}\n";
4950 }
4951
4952 if ($isSVGTearOffType) {
4953 AddToImplIncludes("V8$returnType.h");
4954 AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h");
4955 my $svgNativeType = GetSVGTypeNeedingTearOff($returnType);
4956 # FIXME: Update for all ScriptWrappables.
4957 if (IsDOMNodeType($interfaceName)) {
4958 if ($forMainWorldSuffix eq "ForMainWorld") {
4959 $code .= $indent . "v8SetReturnValueForMainWorld(args, WTF::getP tr(${svgNativeType}::create($return), args.Holder()));\n";
4960 } else {
4961 $code .= $indent . "v8SetReturnValueFast(args, WTF::getPtr(${svg NativeType}::create($return)), imp);\n";
4962 }
4963 } else {
4964 $code .= $indent . "v8SetReturnValue${forMainWorldSuffix}(args, WTF: :getPtr(${svgNativeType}::create($return)), args.Holder());\n";
4965 }
4966 $code .= $indent . "return;\n";
4967 return $code;
4968 }
4969
4970 # If the implementing class is a POD type, commit changes
4971 if (IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$ /) {
4972 $code .= $indent . "wrapper->commitChange();\n";
4973 }
4974
4975 $return .= ".release()" if ($returnIsRef);
4976
4977 my $nativeValue;
4978 # FIXME: Update for all ScriptWrappables.
4979 if (IsDOMNodeType($interfaceName)) {
4980 $nativeValue = NativeToJSValue($function->type, $function->extendedAttri butes, $return, $indent, "", "args.Holder()", "args.GetIsolate()", "args", "imp" , $forMainWorldSuffix, "return");
4981 } else {
4982 $nativeValue = NativeToJSValue($function->type, $function->extendedAttri butes, $return, $indent, "", "args.Holder()", "args.GetIsolate()", "args", 0, $f orMainWorldSuffix, "return");
4983 }
4984
4985 $code .= $nativeValue . "\n";
4986 $code .= $indent . "return;\n";
4987
4988 return $code;
4989 }
4990
4991 sub GetNativeType
4992 {
4993 my $type = shift;
4994 my $extendedAttributes = shift;
4995 my $isParameter = shift;
4996
4997 my $svgNativeType = GetSVGTypeNeedingTearOff($type);
4998 if ($svgNativeType) {
4999 if ($svgNativeType =~ /List$/) {
5000 return "${svgNativeType}*";
5001 } else {
5002 return "RefPtr<${svgNativeType} >";
5003 }
5004 }
5005
5006 return "float" if $type eq "float";
5007 return "double" if $type eq "double";
5008 return "int" if $type eq "long" or $type eq "int" or $type eq "short" or $ty pe eq "byte";
5009 if ($type eq "unsigned long" or $type eq "unsigned int" or $type eq "unsigne d short" or $type eq "octet") {
5010 return "unsigned";
5011 }
5012 return "long long" if $type eq "long long";
5013 return "unsigned long long" if $type eq "unsigned long long";
5014 return "bool" if $type eq "boolean";
5015
5016 if (($type eq "DOMString" || IsEnumType($type)) and $isParameter) {
5017 # FIXME: This implements [TreatNullAs=NullString] and [TreatUndefinedAs= NullString],
5018 # but the Web IDL spec requires [TreatNullAs=EmptyString] and [TreatUnde finedAs=EmptyString].
5019 my $mode = "";
5020 if (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"Tre atNullAs"} eq "NullString") and ($extendedAttributes->{"TreatUndefinedAs"} and $ extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) {
5021 $mode = "WithUndefinedOrNullCheck";
5022 } elsif (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes-> {"TreatNullAs"} eq "NullString") or $extendedAttributes->{"Reflect"}) {
5023 $mode = "WithNullCheck";
5024 }
5025 # FIXME: Add the case for 'elsif ($attributeOrParameter->extendedAttribu tes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes->{"Treat UndefinedAs"} eq "NullString"))'.
5026 return "V8StringResource<$mode>";
5027 }
5028
5029 return "String" if $type eq "DOMString" or IsEnumType($type);
5030
5031 return "ScriptPromise" if $type eq "Promise";
5032
5033 return "Range::CompareHow" if $type eq "CompareHow";
5034 return "DOMTimeStamp" if $type eq "DOMTimeStamp";
5035 return "double" if $type eq "Date";
5036 return "ScriptValue" if $type eq "any" or IsCallbackFunctionType($type);
5037 return "Dictionary" if $type eq "Dictionary";
5038
5039 return "RefPtr<DOMStringList>" if $type eq "DOMStringList";
5040 return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener" ;
5041 return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
5042 return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue";
5043 return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
5044
5045 die "UnionType is not supported" if IsUnionType($type);
5046
5047 if (IsTypedArrayType($type)) {
5048 return $isParameter ? "${type}*" : "RefPtr<${type}>";
5049 }
5050
5051 # We need to check [ImplementedAs] extended attribute for wrapper types.
5052 if (IsWrapperType($type)) {
5053 my $interface = ParseInterface($type);
5054 my $implClassName = GetImplName($interface);
5055 return $isParameter ? "${implClassName}*" : "RefPtr<${implClassName}>";
5056 }
5057 return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
5058
5059 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5060
5061 if ($arrayOrSequenceType) {
5062 my $nativeType = GetNativeType($arrayOrSequenceType);
5063 $nativeType .= " " if ($nativeType =~ />$/);
5064 return "Vector<${nativeType}>";
5065 }
5066
5067 # Default, assume native type is a pointer with same type name as idl type
5068 return "${type}*";
5069 }
5070
5071 sub GetNativeTypeForCallbacks
5072 {
5073 my $type = shift;
5074 return "const String&" if $type eq "DOMString";
5075 return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValu e";
5076
5077 # Callbacks use raw pointers, so pass isParameter = 1
5078 my $nativeType = GetNativeType($type, {}, "parameter");
5079 return "const $nativeType&" if $nativeType =~ /^Vector/;
5080 return $nativeType;
5081 }
5082
5083 sub JSValueToNativeStatement
5084 {
5085 my $type = shift;
5086 my $extendedAttributes = shift;
5087 my $jsValue = shift;
5088 my $variableName = shift;
5089 my $indent = shift;
5090 my $getIsolate = shift;
5091
5092 my $nativeType = GetNativeType($type, $extendedAttributes, "parameter");
5093 my $native_value = JSValueToNative($type, $extendedAttributes, $jsValue, $ge tIsolate);
5094 my $code = "";
5095 if ($type eq "DOMString" || IsEnumType($type)) {
5096 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8St ringResource/;
5097 if ($type eq "DOMString" or IsEnumType($type)) {
5098 $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType , $variableName, $native_value);\n"
5099 } else {
5100 $code .= $indent . "$nativeType $variableName($native_value, true);\ n";
5101 }
5102 } elsif ($extendedAttributes->{"EnforceRange"}) {
5103 $code .= $indent . "V8TRYCATCH_WITH_TYPECHECK_VOID($nativeType, $variabl eName, $native_value, $getIsolate);\n";
5104 } else {
5105 $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_ value);\n";
5106 }
5107 return $code;
5108 }
5109
5110
5111 sub JSValueToNative
5112 {
5113 my $type = shift;
5114 my $extendedAttributes = shift;
5115 my $value = shift;
5116 my $getIsolate = shift;
5117
5118 my $intConversion = $extendedAttributes->{"EnforceRange"} ? "EnforceRange" : "NormalConversion";
5119
5120 return "$value->BooleanValue()" if $type eq "boolean";
5121 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $t ype eq "double";
5122
5123 if ($intConversion ne "NormalConversion") {
5124 return "toInt8($value, $intConversion, ok)" if $type eq "byte";
5125 return "toUInt8($value, $intConversion, ok)" if $type eq "octet";
5126 return "toInt32($value, $intConversion, ok)" if $type eq "long" or $type eq "short";
5127 return "toUInt32($value, $intConversion, ok)" if $type eq "unsigned long " or $type eq "unsigned short";
5128 return "toInt64($value, $intConversion, ok)" if $type eq "long long";
5129 return "toUInt64($value, $intConversion, ok)" if $type eq "unsigned long long";
5130 } else {
5131 return "toInt8($value)" if $type eq "byte";
5132 return "toUInt8($value)" if $type eq "octet";
5133 return "toInt32($value)" if $type eq "long" or $type eq "short";
5134 return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsig ned short";
5135 return "toInt64($value)" if $type eq "long long";
5136 return "toUInt64($value)" if $type eq "unsigned long long";
5137 }
5138 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "C ompareHow";
5139 return "toWebCoreDate($value)" if $type eq "Date";
5140 return "toDOMStringList($value, $getIsolate)" if $type eq "DOMStringList";
5141
5142 if ($type eq "DOMString" or IsEnumType($type)) {
5143 return $value;
5144 }
5145
5146 if ($type eq "SerializedScriptValue") {
5147 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
5148 return "SerializedScriptValue::create($value, $getIsolate)";
5149 }
5150
5151 if ($type eq "Dictionary") {
5152 AddToImplIncludes("bindings/v8/Dictionary.h");
5153 return "Dictionary($value, $getIsolate)";
5154 }
5155
5156 if ($type eq "any" || IsCallbackFunctionType($type)) {
5157 AddToImplIncludes("bindings/v8/ScriptValue.h");
5158 return "ScriptValue($value)";
5159 }
5160
5161 if ($type eq "Promise") {
5162 AddToImplIncludes("bindings/v8/ScriptPromise.h");
5163 return "ScriptPromise($value)";
5164 }
5165
5166 if ($type eq "NodeFilter") {
5167 return "toNodeFilter($value, $getIsolate)";
5168 }
5169
5170 if ($type eq "MediaQueryListListener") {
5171 AddToImplIncludes("core/css/MediaQueryListListener.h");
5172 return "MediaQueryListListener::create(" . $value . ")";
5173 }
5174
5175 if ($type eq "EventTarget") {
5176 return "V8DOMWrapper::isDOMWrapper($value) ? toWrapperTypeInfo(v8::Handl e<v8::Object>::Cast($value))->toEventTarget(v8::Handle<v8::Object>::Cast($value) ) : 0";
5177 }
5178
5179 if (IsTypedArrayType($type)) {
5180 AddIncludesForType($type);
5181 return "$value->Is${type}() ? V8${type}::toNative(v8::Handle<v8::${type} >::Cast($value)) : 0"
5182 }
5183
5184 if ($type eq "XPathNSResolver") {
5185 return "toXPathNSResolver($value, $getIsolate)";
5186 }
5187
5188 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5189
5190 if ($arrayOrSequenceType) {
5191 if (IsRefPtrType($arrayOrSequenceType)) {
5192 AddToImplIncludes("V8${arrayOrSequenceType}.h");
5193 return "(toRefPtrNativeArray<${arrayOrSequenceType}, V8${arrayOrSequ enceType}>($value, $getIsolate))";
5194 }
5195 return "toNativeArray<" . GetNativeType($arrayOrSequenceType) . ">($valu e, $getIsolate)";
5196 }
5197
5198 AddIncludesForType($type);
5199
5200 AddToImplIncludes("V8${type}.h");
5201 return "V8${type}::HasInstance($value, $getIsolate, worldType($getIsolate)) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0";
5202 }
5203
5204 sub CreateCustomSignature
5205 {
5206 my $function = shift;
5207 my $count = @{$function->parameters};
5208 my $name = $function->name;
5209 my $code = " const int ${name}Argc = ${count};\n" .
5210 " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { ";
5211 my $first = 1;
5212 foreach my $parameter (@{$function->parameters}) {
5213 if ($first) { $first = 0; }
5214 else { $code .= ", "; }
5215 if (IsWrapperType($parameter->type) && not IsTypedArrayType($parameter-> type)) {
5216 if ($parameter->type eq "XPathNSResolver") {
5217 # Special case for XPathNSResolver. All other browsers accepts a callable,
5218 # so, even though it's against IDL, accept objects here.
5219 $code .= "v8::Handle<v8::FunctionTemplate>()";
5220 } else {
5221 my $type = $parameter->type;
5222 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5223
5224 if ($arrayOrSequenceType) {
5225 if (IsRefPtrType($arrayOrSequenceType)) {
5226 AddIncludesForType($arrayOrSequenceType);
5227 } else {
5228 $code .= "v8::Handle<v8::FunctionTemplate>()";
5229 next;
5230 }
5231 } else {
5232 AddIncludesForType($type);
5233 }
5234 $code .= "V8PerIsolateData::from(isolate)->rawTemplate(&V8${type }::info, currentWorldType)";
5235 }
5236 } else {
5237 $code .= "v8::Handle<v8::FunctionTemplate>()";
5238 }
5239 }
5240 $code .= " };\n";
5241 $code .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::Ne w(desc, ${name}Argc, ${name}Argv);\n";
5242 return $code;
5243 }
5244
5245
5246 sub RequiresCustomSignature
5247 {
5248 my $function = shift;
5249 # No signature needed for Custom function
5250 if (HasCustomMethod($function->extendedAttributes)) {
5251 return 0;
5252 }
5253 # No signature needed for overloaded function
5254 if (@{$function->{overloads}} > 1) {
5255 return 0;
5256 }
5257 if ($function->isStatic) {
5258 return 0;
5259 }
5260 # Type checking is performed in the generated code
5261 if ($function->extendedAttributes->{"StrictTypeChecking"}) {
5262 return 0;
5263 }
5264 foreach my $parameter (@{$function->parameters}) {
5265 if (($parameter->isOptional && !$parameter->extendedAttributes->{"Defaul t"}) || IsCallbackInterface($parameter->type)) {
5266 return 0;
5267 }
5268 }
5269
5270 foreach my $parameter (@{$function->parameters}) {
5271 if (IsWrapperType($parameter->type)) {
5272 return 1;
5273 }
5274 }
5275 return 0;
5276 }
5277
5278 sub IsUnionType
5279 {
5280 my $type = shift; # string or UnionType
5281 if(ref($type) eq "UnionType") {
5282 die "Currently only 2 values of non-union type is supported as union typ e.\n" unless @{$type->unionMemberTypes} == 2;
5283 return 1;
5284 }
5285 return 0;
5286 }
5287
5288 sub IsWrapperType
5289 {
5290 my $type = shift;
5291 return 0 if GetArrayType($type);
5292 return 0 if GetSequenceType($type);
5293 return 0 if IsCallbackFunctionType($type);
5294 return 0 if IsEnumType($type);
5295 return 0 if IsPrimitiveType($type);
5296 return 0 if $type eq "DOMString";
5297 return 0 if $type eq "Promise";
5298 return !$nonWrapperTypes{$type};
5299 }
5300
5301 sub IsCallbackInterface
5302 {
5303 my $type = shift;
5304 return 0 unless IsWrapperType($type);
5305 return 0 if IsTypedArrayType($type);
5306
5307 my $idlFile = IDLFileForInterface($type)
5308 or die("Could NOT find IDL file for interface \"$type\"!\n");
5309
5310 open FILE, "<", $idlFile;
5311 my @lines = <FILE>;
5312 close FILE;
5313
5314 my $fileContents = join('', @lines);
5315 return ($fileContents =~ /callback\s+interface\s+(\w+)/gs);
5316 }
5317
5318 sub GetNativeTypeOfTypedArray
5319 {
5320 my $interface = shift;
5321 my $interfaceName = $interface->name;
5322 die "TypedArray of unknown type is found" unless $typedArrayHash{$interface- >name};
5323 return @{$typedArrayHash{$interface->name}};
5324 }
5325
5326 sub IsDOMNodeType
5327 {
5328 my $type = shift;
5329
5330 return 1 if $type eq 'Attr';
5331 return 1 if $type eq 'CDATASection';
5332 return 1 if $type eq 'CharacterData';
5333 return 1 if $type eq 'Comment';
5334 return 1 if $type eq 'Document';
5335 return 1 if $type eq 'DocumentFragment';
5336 return 1 if $type eq 'DocumentType';
5337 return 1 if $type eq 'Element';
5338 return 1 if $type eq 'Entity';
5339 return 1 if $type eq 'HTMLDocument';
5340 return 1 if $type eq 'Node';
5341 return 1 if $type eq 'Notation';
5342 return 1 if $type eq 'ProcessingInstruction';
5343 return 1 if $type eq 'ShadowRoot';
5344 return 1 if $type eq 'SVGDocument';
5345 return 1 if $type eq 'Text';
5346
5347 return 1 if $type =~ /^HTML.*Element$/;
5348 return 1 if $type =~ /^SVG.*Element$/;
5349
5350 return 1 if $type eq 'TestNode';
5351
5352 return 0;
5353 }
5354
5355
5356 sub NativeToJSValue
5357 {
5358 my $type = shift;
5359 my $extendedAttributes = shift;
5360 my $nativeValue = shift;
5361 my $indent = shift; # added before every line
5362 my $receiver = shift; # "return" or "<variableName> ="
5363 my $getCreationContext = shift;
5364 my $getIsolate = shift;
5365 die "An Isolate is mandatory for native value => JS value conversion." unles s $getIsolate;
5366 my $getCallbackInfo = shift || "";
5367 my $getCallbackInfoArg = $getCallbackInfo ? ", $getCallbackInfo" : "";
5368 my $getScriptWrappable = shift || "";
5369 my $getScriptWrappableArg = $getScriptWrappable ? ", $getScriptWrappable" : "";
5370 my $forMainWorldSuffix = shift || "";
5371 my $returnValueArg = shift || 0;
5372 my $isReturnValue = $returnValueArg eq "return";
5373
5374 if (IsUnionType($type)) {
5375 my $types = $type->unionMemberTypes;
5376 my @codes = ();
5377 for my $i (0 .. scalar(@$types)-1) {
5378 my $unionMemberType = $types->[$i];
5379 my $unionMemberNumber = $i + 1;
5380 my $unionMemberVariable = $nativeValue . $i;
5381 my $unionMemberEnabledVariable = $nativeValue . $i . "Enabled";
5382 my $unionMemberNativeValue = $unionMemberVariable;
5383 $unionMemberNativeValue .= ".release()" if (IsRefPtrType($unionMembe rType));
5384 my $returnJSValueCode = NativeToJSValue($unionMemberType, $extendedA ttributes, $unionMemberNativeValue, $indent . " ", $receiver, $getCreationCon text, $getIsolate, $getCallbackInfo, $getScriptWrappable, $forMainWorldSuffix, $ returnValueArg);
5385 my $code = "";
5386 if ($isReturnValue) {
5387 $code .= "${indent}if (${unionMemberEnabledVariable}) {\n";
5388 $code .= "${returnJSValueCode}\n";
5389 $code .= "${indent} return;\n";
5390 $code .= "${indent}}\n";
5391 } else {
5392 $code .= "${indent}if (${unionMemberEnabledVariable})\n";
5393 $code .= "${returnJSValueCode}";
5394 }
5395 push @codes, $code;
5396 }
5397 return join "\n", @codes;
5398 }
5399
5400 if ($type eq "boolean") {
5401 return "${indent}v8SetReturnValueBool(${getCallbackInfo}, ${nativeValue} );" if $isReturnValue;
5402 return "$indent$receiver v8Boolean($nativeValue, $getIsolate);";
5403 }
5404
5405 if ($type eq "void") { # equivalent to v8Undefined()
5406 return "" if $isReturnValue;
5407 return "$indent$receiver v8Undefined();"
5408 }
5409
5410 # HTML5 says that unsigned reflected attributes should be in the range
5411 # [0, 2^31). When a value isn't in this range, a default value (or 0)
5412 # should be returned instead.
5413 if ($extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
5414 $nativeValue =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
5415 return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, std::max(0 , ${nativeValue}));" if $isReturnValue;
5416 return "$indent$receiver v8::Integer::NewFromUnsigned(std::max(0, " . $n ativeValue . "), $getIsolate);";
5417 }
5418
5419 my $nativeType = GetNativeType($type);
5420 if ($nativeType eq "int") {
5421 return "${indent}v8SetReturnValueInt(${getCallbackInfo}, ${nativeValue}) ;" if $isReturnValue;
5422 return "$indent$receiver v8::Integer::New($nativeValue, $getIsolate);";
5423 }
5424
5425 if ($nativeType eq "unsigned") {
5426 return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, ${nativeVa lue});" if $isReturnValue;
5427 return "$indent$receiver v8::Integer::NewFromUnsigned($nativeValue, $get Isolate);";
5428 }
5429
5430 if ($type eq "Date") {
5431 return "${indent}v8SetReturnValue(${getCallbackInfo}, v8DateOrNull($nati veValue, $getIsolate));" if $isReturnValue;
5432 return "$indent$receiver v8DateOrNull($nativeValue, $getIsolate);"
5433 }
5434
5435 # long long and unsigned long long are not representable in ECMAScript.
5436 if ($type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTi meStamp") {
5437 return "${indent}v8SetReturnValue(${getCallbackInfo}, static_cast<double >($nativeValue));" if $isReturnValue;
5438 return "$indent$receiver v8::Number::New($getIsolate, static_cast<double >($nativeValue));";
5439 }
5440
5441 if (IsPrimitiveType($type)) {
5442 die "unexpected type $type" if not ($type eq "float" or $type eq "double ");
5443 return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue});" if $isReturnValue;
5444 return "$indent$receiver v8::Number::New($getIsolate, $nativeValue);";
5445 }
5446
5447 if ($nativeType eq "ScriptValue" or $nativeType eq "ScriptPromise") {
5448 return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue}.v8V alue());" if $isReturnValue;
5449 return "$indent$receiver $nativeValue.v8Value();";
5450 }
5451
5452 my $conv = $extendedAttributes->{"TreatReturnedNullStringAs"};
5453 if (($type eq "DOMString" || IsEnumType($type)) && $isReturnValue) {
5454 my $functionSuffix = "";
5455 if (defined $conv) {
5456 if ($conv eq "Null") {
5457 $functionSuffix = "OrNull";
5458 } elsif ($conv eq "Undefined") {
5459 $functionSuffix = "OrUndefined";
5460 } else {
5461 die "Unknown value for TreatReturnedNullStringAs extended attrib ute";
5462 }
5463 }
5464 return "${indent}v8SetReturnValueString${functionSuffix}(${getCallbackIn fo}, $nativeValue, $getIsolate);";
5465 }
5466
5467 if ($type eq "DOMString" or IsEnumType($type)) {
5468 my $returnValue = "";
5469 if (defined $conv) {
5470 if ($conv eq "Null") {
5471 $returnValue = "v8StringOrNull($nativeValue, $getIsolate)";
5472 } elsif ($conv eq "Undefined") {
5473 $returnValue = "v8StringOrUndefined($nativeValue, $getIsolate)";
5474 } else {
5475 die "Unknown value for TreatReturnedNullStringAs extended attrib ute";
5476 }
5477 } else {
5478 $returnValue = "v8String($nativeValue, $getIsolate)";
5479 }
5480 return "$indent$receiver $returnValue;";
5481 }
5482
5483 my $arrayOrSequenceType = GetArrayOrSequenceType($type);
5484
5485 if ($arrayOrSequenceType) {
5486 if (IsRefPtrType($arrayOrSequenceType)) {
5487 AddIncludesForType($arrayOrSequenceType);
5488 }
5489 return "${indent}v8SetReturnValue(${getCallbackInfo}, v8Array($nativeVal ue, $getIsolate));" if $isReturnValue;
5490 return "$indent$receiver v8Array($nativeValue, $getIsolate);";
5491 }
5492
5493 AddIncludesForType($type);
5494
5495 if ($type eq "SerializedScriptValue") {
5496 my $returnValue = "$nativeValue ? $nativeValue->deserialize() : v8::Hand le<v8::Value>(v8::Null($getIsolate))";
5497 return "${indent}v8SetReturnValue(${getCallbackInfo}, $returnValue);" if $isReturnValue;
5498 return "$indent$receiver $returnValue;";
5499 }
5500
5501 AddToImplIncludes("wtf/RefPtr.h");
5502 AddToImplIncludes("wtf/GetPtr.h");
5503
5504 if ($getScriptWrappable) {
5505 # FIXME: Use safe handles
5506 if ($isReturnValue) {
5507 if ($forMainWorldSuffix eq "ForMainWorld") {
5508 return "${indent}v8SetReturnValueForMainWorld(${getCallbackInfo} , $nativeValue, $getCallbackInfo.Holder());";
5509 }
5510 return "${indent}v8SetReturnValueFast(${getCallbackInfo}, $nativeVal ue$getScriptWrappableArg);";
5511 }
5512 }
5513 # FIXME: Use safe handles
5514 return "${indent}v8SetReturnValue(${getCallbackInfo}, $nativeValue, $getCrea tionContext);" if $isReturnValue;
5515 return "$indent$receiver toV8($nativeValue, $getCreationContext, $getIsolate );";
5516 }
5517
5518 sub WriteData
5519 {
5520 my $object = shift;
5521 my $interface = shift;
5522 my $outputDirectory = shift;
5523
5524 my $name = $interface->name;
5525 my $headerFileName = "$outputDirectory/V8$name.h";
5526 my $implFileName = "$outputDirectory/V8$name.cpp";
5527
5528 my @includes = ();
5529 foreach my $include (keys %implIncludes) {
5530 push @includes, "\"$include\"";
5531 }
5532
5533 #FIXME: do not treat main header special
5534 my $mainInclude = "\"V8$name.h\"";
5535 foreach my $include (sort @includes) {
5536 $implementation{includes}->add("#include $include\n") unless $include eq $mainInclude;
5537 }
5538 $implementation{includes}->add("\n") unless $interface->isCallback;
5539 WriteFileIfChanged($implFileName, $implementation{root}->toString());
5540
5541 %implIncludes = ();
5542
5543 WriteFileIfChanged($headerFileName, $header{root}->toString());
5544 }
5545
5546 sub ConvertToV8StringResource
5547 {
5548 my $attributeOrParameter = shift;
5549 my $nativeType = shift;
5550 my $variableName = shift;
5551 my $value = shift;
5552
5553 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8String Resource/;
5554 if ($attributeOrParameter->type eq "DOMString" or IsEnumType($attributeOrPar ameter->type)) {
5555 return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $value);"
5556 } else {
5557 return "$nativeType $variableName($value, true);";
5558 }
5559 }
5560
5561 # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled.
5562 sub GetRuntimeEnableFunctionName
5563 {
5564 my $signature = shift;
5565
5566 # Given [EnabledAtRuntime=FeatureName],
5567 # return RuntimeEnabledFeatures::{featureName}Enabled;
5568 my $featureName = ToMethodName($signature->extendedAttributes->{"EnabledAtRu ntime"});
5569 return "RuntimeEnabledFeatures::${featureName}Enabled";
5570 }
5571
5572 sub GetContextEnableFunction
5573 {
5574 my $signature = shift;
5575
5576 # Given [EnabledPerContext=FeatureName],
5577 # return ContextFeatures::{featureName}Enabled
5578 my $featureName = ToMethodName($signature->extendedAttributes->{"EnabledPerC ontext"});
5579 return "ContextFeatures::${featureName}Enabled";
5580 }
5581
5582 sub GetPassRefPtrType
5583 {
5584 my $v8ClassName = shift;
5585
5586 my $angleBracketSpace = $v8ClassName =~ />$/ ? " " : "";
5587 return "PassRefPtr<${v8ClassName}${angleBracketSpace}>";
5588 }
5589
5590 sub WriteFileIfChanged
5591 {
5592 my $fileName = shift;
5593 my $contents = shift;
5594
5595 if (-f $fileName && $writeFileOnlyIfChanged) {
5596 open FH, "<", $fileName or die "Couldn't open $fileName: $!\n";
5597 my @lines = <FH>;
5598 my $oldContents = join "", @lines;
5599 close FH;
5600 return if $contents eq $oldContents;
5601 }
5602 open FH, ">", $fileName or die "Couldn't open $fileName: $!\n";
5603 print FH $contents;
5604 close FH;
5605 }
5606
5607 sub ForAllParents
5608 {
5609 my $interface = shift;
5610 my $beforeRecursion = shift;
5611 my $afterRecursion = shift;
5612
5613 my $recurse;
5614 $recurse = sub {
5615 my $currentInterface = shift;
5616
5617 if ($currentInterface->parent) {
5618 my $parentInterface = ParseInterface($currentInterface->parent);
5619 if ($beforeRecursion) {
5620 &$beforeRecursion($parentInterface) eq 'prune' and return;
5621 }
5622 &$recurse($parentInterface);
5623 &$afterRecursion($parentInterface) if $afterRecursion;
5624 }
5625 };
5626
5627 &$recurse($interface);
5628 }
5629
5630 sub FindSuperMethod
5631 {
5632 my ($interface, $functionName) = @_;
5633 my $indexer;
5634 ForAllParents($interface, undef, sub {
5635 my $currentInterface = shift;
5636 foreach my $function (@{$currentInterface->functions}) {
5637 if ($function->name eq $functionName) {
5638 $indexer = $function;
5639 return 'prune';
5640 }
5641 }
5642 });
5643 return $indexer;
5644 }
5645
5646 sub IsConstructorTemplate
5647 {
5648 my $interface = shift;
5649 my $template = shift;
5650
5651 return $interface->extendedAttributes->{"ConstructorTemplate"} && $interface ->extendedAttributes->{"ConstructorTemplate"} eq $template;
5652 }
5653
5654 sub IsPrimitiveType
5655 {
5656 my $type = shift;
5657
5658 return 1 if $primitiveTypeHash{$type};
5659 return 0;
5660 }
5661
5662 sub IsCallbackFunctionType
5663 {
5664 my $type = shift;
5665
5666 return 1 if $callbackFunctionTypeHash{$type};
5667 return 0;
5668 }
5669
5670 sub IsEnumType
5671 {
5672 my $type = shift;
5673
5674 return 1 if $enumTypeHash{$type};
5675 return 0;
5676 }
5677
5678 sub ValidEnumValues
5679 {
5680 my $type = shift;
5681
5682 return @{$enumTypeHash{$type}};
5683 }
5684
5685 sub IsSVGTypeNeedingTearOff
5686 {
5687 my $type = shift;
5688
5689 return 1 if $svgTypeNeedingTearOff{$type};
5690 return 0;
5691 }
5692
5693 sub IsSVGTypeWithWritablePropertiesNeedingTearOff
5694 {
5695 my $type = shift;
5696
5697 return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type};
5698 return 0;
5699 }
5700
5701 sub IsTypedArrayType
5702 {
5703 my $type = shift;
5704 return 1 if $typedArrayHash{$type};
5705 return 0;
5706 }
5707
5708 sub IsRefPtrType
5709 {
5710 my $type = shift;
5711
5712 return 0 if $type eq "any";
5713 return 0 if IsPrimitiveType($type);
5714 return 0 if GetArrayType($type);
5715 return 0 if GetSequenceType($type);
5716 return 0 if $type eq "DOMString";
5717 return 0 if $type eq "Promise";
5718 return 0 if IsCallbackFunctionType($type);
5719 return 0 if IsEnumType($type);
5720 return 0 if IsUnionType($type);
5721
5722 return 1;
5723 }
5724
5725 sub GetSVGTypeNeedingTearOff
5726 {
5727 my $type = shift;
5728
5729 return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type} ;
5730 return undef;
5731 }
5732
5733 sub GetSVGWrappedTypeNeedingTearOff
5734 {
5735 my $type = shift;
5736
5737 my $svgTypeNeedingTearOff = GetSVGTypeNeedingTearOff($type);
5738 return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff;
5739
5740 if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) {
5741 $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//;
5742 } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) {
5743 $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//;
5744 } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) {
5745 $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//;
5746 } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) {
5747 $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//;
5748 }
5749
5750 $svgTypeNeedingTearOff =~ s/>//;
5751 return $svgTypeNeedingTearOff;
5752 }
5753
5754 sub IsSVGAnimatedType
5755 {
5756 my $type = shift;
5757
5758 return $type =~ /^SVGAnimated/;
5759 }
5760
5761 sub GetSequenceType
5762 {
5763 my $type = shift;
5764
5765 return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/;
5766 return "";
5767 }
5768
5769 sub GetArrayType
5770 {
5771 my $type = shift;
5772
5773 return $1 if $type =~ /^([\w\d_\s]+)\[\]/;
5774 return "";
5775 }
5776
5777 sub GetArrayOrSequenceType
5778 {
5779 my $type = shift;
5780
5781 return GetArrayType($type) || GetSequenceType($type);
5782 }
5783
5784 sub AssertNotSequenceType
5785 {
5786 my $type = shift;
5787 die "Sequences must not be used as the type of an attribute, constant or exc eption field." if GetSequenceType($type);
5788 }
5789
5790 sub FirstLetterToUpperCase
5791 {
5792 my $param = shift;
5793 my $ret = ucfirst($param);
5794 # xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang.
5795 $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/;
5796 $ret =~ s/Css/CSS/ if $ret =~ /^Css[^T]/; # css -> setCSS, except setCssTex t.
5797 $ret =~ s/Ime/IME/ if $ret =~ /^Ime/; # ime -> setIME
5798 $ret =~ s/Svg/SVG/ if $ret =~ /^Svg/; # svg -> setSVG
5799 return $ret;
5800 }
5801
5802 # URL becomes url, but SetURL becomes setURL.
5803 sub ToMethodName
5804 {
5805 my $param = shift;
5806 my $ret = lcfirst($param);
5807 $ret =~ s/hTML/html/ if $ret =~ /^hTML/;
5808 $ret =~ s/iME/ime/ if $ret =~ /^iME/;
5809 $ret =~ s/uRL/url/ if $ret =~ /^uRL/;
5810 $ret =~ s/jS/js/ if $ret =~ /^jS/;
5811 $ret =~ s/xML/xml/ if $ret =~ /^xML/;
5812 $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/;
5813 $ret =~ s/cSS/css/ if $ret =~ /^cSS/;
5814
5815 # For HTML5 FileSystem API Flags attributes.
5816 # (create is widely used to instantiate an object and must be avoided.)
5817 $ret =~ s/^create/isCreate/ if $ret =~ /^create$/;
5818 $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/;
5819
5820 return $ret;
5821 }
5822
5823 sub NamespaceForAttributeName
5824 {
5825 my ($interfaceName, $attributeName) = @_;
5826 return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$ attributeName};
5827 return "HTMLNames";
5828 }
5829
5830 # Identifies overloaded functions and for each function adds an array with
5831 # links to its respective overloads (including itself).
5832 sub LinkOverloadedFunctions
5833 {
5834 my $interface = shift;
5835
5836 my %nameToFunctionsMap = ();
5837 foreach my $function (@{$interface->functions}) {
5838 my $name = $function->name;
5839 $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name} or !$name; # Nameless functions cannot be overloaded
5840 push(@{$nameToFunctionsMap{$name}}, $function);
5841 $function->{overloads} = $nameToFunctionsMap{$name};
5842 $function->{overloadIndex} = @{$nameToFunctionsMap{$name}};
5843 }
5844 }
5845
5846 sub AttributeNameForGetterAndSetter
5847 {
5848 my $attribute = shift;
5849
5850 my $attributeName = GetImplName($attribute);
5851 if ($attribute->extendedAttributes->{"ImplementedAs"}) {
5852 $attributeName = $attribute->extendedAttributes->{"ImplementedAs"};
5853 }
5854 my $attributeType = $attribute->type;
5855
5856 return $attributeName;
5857 }
5858
5859 sub ContentAttributeName
5860 {
5861 my ($interfaceName, $attribute) = @_;
5862
5863 my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"};
5864 return undef if !$contentAttributeName;
5865
5866 $contentAttributeName = lc AttributeNameForGetterAndSetter($attribute) if $c ontentAttributeName eq "VALUE_IS_MISSING";
5867
5868 my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeN ame);
5869
5870 AddToImplIncludes("${namespace}.h");
5871 # Attr (not Attribute) used in core content attributes
5872 return "WebCore::${namespace}::${contentAttributeName}Attr";
5873 }
5874
5875 sub GetterExpression
5876 {
5877 my ($interfaceName, $attribute) = @_;
5878
5879 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute);
5880
5881 if (!$contentAttributeName) {
5882 return (ToMethodName(AttributeNameForGetterAndSetter($attribute)));
5883 }
5884
5885 my $functionName;
5886 if ($attribute->extendedAttributes->{"URL"}) {
5887 $functionName = "getURLAttribute";
5888 } elsif ($attribute->type eq "boolean") {
5889 $functionName = "fastHasAttribute";
5890 } elsif ($attribute->type eq "long") {
5891 $functionName = "getIntegralAttribute";
5892 } elsif ($attribute->type eq "unsigned long") {
5893 $functionName = "getUnsignedIntegralAttribute";
5894 } else {
5895 if ($contentAttributeName eq "WebCore::HTMLNames::idAttr") {
5896 $functionName = "getIdAttribute";
5897 $contentAttributeName = "";
5898 } elsif ($contentAttributeName eq "WebCore::HTMLNames::nameAttr") {
5899 $functionName = "getNameAttribute";
5900 $contentAttributeName = "";
5901 } elsif ($contentAttributeName eq "WebCore::HTMLNames::classAttr") {
5902 $functionName = "getClassAttribute";
5903 $contentAttributeName = "";
5904 } else {
5905 # We cannot use fast attributes for animated SVG types.
5906 $functionName = IsSVGAnimatedType($attribute->type) ? "getAttribute" : "fastGetAttribute";
5907 }
5908 }
5909
5910 return ($functionName, $contentAttributeName);
5911 }
5912
5913 sub SetterExpression
5914 {
5915 my ($interfaceName, $attribute) = @_;
5916
5917 my $contentAttributeName = ContentAttributeName($interfaceName, $attribute);
5918
5919 if (!$contentAttributeName) {
5920 return ("set" . FirstLetterToUpperCase(AttributeNameForGetterAndSetter($ attribute)));
5921 }
5922
5923 my $functionName;
5924 if ($attribute->type eq "boolean") {
5925 $functionName = "setBooleanAttribute";
5926 } elsif ($attribute->type eq "long") {
5927 $functionName = "setIntegralAttribute";
5928 } elsif ($attribute->type eq "unsigned long") {
5929 $functionName = "setUnsignedIntegralAttribute";
5930 } else {
5931 $functionName = "setAttribute";
5932 }
5933
5934 return ($functionName, $contentAttributeName);
5935 }
5936
5937 sub GenerateConditionalString
5938 {
5939 my $node = shift;
5940
5941 my $conditional = $node->extendedAttributes->{"Conditional"};
5942 if ($conditional) {
5943 return GenerateConditionalStringFromAttributeValue($conditional);
5944 } else {
5945 return "";
5946 }
5947 }
5948
5949 sub GenerateConditionalStringFromAttributeValue
5950 {
5951 my $conditional = shift;
5952
5953 my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : '' ));
5954 if ($operator) {
5955 # Avoid duplicated conditions.
5956 my %conditions;
5957 map { $conditions{$_} = 1 } split('\\' . $operator, $conditional);
5958 return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %condi tions) . ")";
5959 } else {
5960 return "ENABLE(" . $conditional . ")";
5961 }
5962 }
5963
5964 sub GenerateCompileTimeCheckForEnumsIfNeeded
5965 {
5966 my $interface = shift;
5967 my $implClassName = GetImplName($interface);
5968 my @checks = ();
5969 # If necessary, check that all constants are available as enums with the sam e value.
5970 if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface ->constants}) {
5971 foreach my $constant (@{$interface->constants}) {
5972 my $reflect = $constant->extendedAttributes->{"Reflect"};
5973 my $name = $reflect ? $reflect : $constant->name;
5974 my $value = $constant->value;
5975
5976 if ($constant->extendedAttributes->{"ImplementedBy"}) {
5977 my $implementedByImplName = GetImplNameFromImplementedBy($consta nt->extendedAttributes->{"ImplementedBy"});
5978 push(@checks, " COMPILE_ASSERT($value == " . $implementedByIm plName . "::$name, TheValueOf${implClassName}_${name}DoesntMatchWithImplementati on);\n");
5979 } else {
5980 push(@checks, " COMPILE_ASSERT($value == ${implClassName}::$n ame, TheValueOf${implClassName}_${name}DoesntMatchWithImplementation);\n");
5981 }
5982 }
5983 }
5984 return @checks;
5985 }
5986
5987 sub ExtendedAttributeContains
5988 {
5989 my $callWith = shift;
5990 return 0 unless $callWith;
5991 my $keyword = shift;
5992
5993 my @callWithKeywords = split /\s*\&\s*/, $callWith;
5994 return grep { $_ eq $keyword } @callWithKeywords;
5995 }
5996
5997 sub InheritsInterface
5998 {
5999 my $interface = shift;
6000 my $interfaceName = shift;
6001 my $found = 0;
6002
6003 return 1 if $interfaceName eq $interface->name;
6004 ForAllParents($interface, sub {
6005 my $currentInterface = shift;
6006 if ($currentInterface->name eq $interfaceName) {
6007 $found = 1;
6008 }
6009 return 1 if $found;
6010 }, 0);
6011
6012 return $found;
6013 }
6014
6015 sub InheritsExtendedAttribute
6016 {
6017 my $interface = shift;
6018 my $extendedAttribute = shift;
6019 my $found = 0;
6020
6021 return 1 if $interface->extendedAttributes->{$extendedAttribute};
6022 ForAllParents($interface, sub {
6023 my $currentInterface = shift;
6024 if ($currentInterface->extendedAttributes->{$extendedAttribute}) {
6025 $found = 1;
6026 }
6027 return 1 if $found;
6028 }, 0);
6029
6030 return $found;
6031 }
6032
6033 1;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698