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