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

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

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

Powered by Google App Engine
This is Rietveld 408576698