OLD | NEW |
| (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; | |
OLD | NEW |