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

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

Issue 121113004: Improve handling of failed integer type conversions. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Update new IDL compiler to match Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> 1 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
2 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com> 2 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
3 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> 3 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
4 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> 4 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
5 # Copyright (C) 2006 Apple Computer, Inc. 5 # Copyright (C) 2006 Apple Computer, Inc.
6 # Copyright (C) 2007, 2008, 2009, 2012 Google Inc. 6 # Copyright (C) 2007, 2008, 2009, 2012 Google Inc.
7 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> 7 # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
8 # Copyright (C) Research In Motion Limited 2010. All rights reserved. 8 # Copyright (C) Research In Motion Limited 2010. All rights reserved.
9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 9 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
10 # Copyright (C) 2012 Ericsson AB. All rights reserved. 10 # Copyright (C) 2012 Ericsson AB. All rights reserved.
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 "short" => 1, 162 "short" => 1,
163 "long" => 1, 163 "long" => 1,
164 "long long" => 1, 164 "long long" => 1,
165 "unsigned short" => 1, 165 "unsigned short" => 1,
166 "unsigned long" => 1, 166 "unsigned long" => 1,
167 "unsigned long long" => 1, 167 "unsigned long long" => 1,
168 "float" => 1, 168 "float" => 1,
169 "double" => 1, 169 "double" => 1,
170 ); 170 );
171 171
172 my %integerTypeHash = ("byte" => 1, 172 # NOTE: For the unsigned types, the "UI" prefix is used (and not
173 "octet" => 1, 173 # "Ui"), so as to match onto the naming of V8Binding conversion
174 "short" => 1, 174 # methods (and not the Typed Array naming scheme for unsigned types.)
175 "long" => 1, 175 my %integerTypeHash = ("byte" => "Int8",
Nils Barth (inactive) 2014/01/06 02:58:09 While you're at it, you could remove the duplicati
sof 2014/01/06 21:01:25 Good idea, done.
176 "long long" => 1, 176 "octet" => "UInt8",
177 "unsigned short" => 1, 177 "short" => "Int16",
178 "unsigned long" => 1, 178 "long" => "Int32",
179 "unsigned long long" => 1, 179 "long long" => "Int64",
180 "unsigned short" => "UInt16",
181 "unsigned long" => "UInt32",
182 "unsigned long long" => "UInt64"
180 ); 183 );
181 184
182 my %nonWrapperTypes = ("CompareHow" => 1, 185 my %nonWrapperTypes = ("CompareHow" => 1,
183 "Dictionary" => 1, 186 "Dictionary" => 1,
184 "EventListener" => 1, 187 "EventListener" => 1,
185 "EventHandler" => 1, 188 "EventHandler" => 1,
186 "MediaQueryListListener" => 1, 189 "MediaQueryListListener" => 1,
187 "NodeFilter" => 1, 190 "NodeFilter" => 1,
188 "SerializedScriptValue" => 1, 191 "SerializedScriptValue" => 1,
189 "any" => 1, 192 "any" => 1,
(...skipping 1732 matching lines...) Expand 10 before | Expand all | Expand 10 after
1922 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8 ::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info)\n"; 1925 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8 ::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info)\n";
1923 } else { 1926 } else {
1924 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8 ::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n"; 1927 $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8 ::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n";
1925 } 1928 }
1926 $code .= "{\n"; 1929 $code .= "{\n";
1927 1930
1928 my $raisesException = $attribute->extendedAttributes->{"RaisesException"}; 1931 my $raisesException = $attribute->extendedAttributes->{"RaisesException"};
1929 my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_ MISSING" or $raisesException eq "Setter"); 1932 my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_ MISSING" or $raisesException eq "Setter");
1930 my $hasStrictTypeChecking = 1 if $attribute->extendedAttributes->{"StrictTyp eChecking"} && IsWrapperType($attrType); # Currently only actually check interf ace types 1933 my $hasStrictTypeChecking = 1 if $attribute->extendedAttributes->{"StrictTyp eChecking"} && IsWrapperType($attrType); # Currently only actually check interf ace types
1931 1934
1935 # Can throw exceptions from accessors or during type conversion.
1936 my $isNumberType = IsIntegerType($attribute->type);
Nils Barth (inactive) 2014/01/06 02:58:09 Would this be clearer as $isIntegerType ? ('Number
sof 2014/01/06 21:01:25 It certainly would be, done.
1937
1932 # We throw exceptions using 'ExceptionState' if the attribute explicitly 1938 # We throw exceptions using 'ExceptionState' if the attribute explicitly
1933 # claims that exceptions may be raised, or if a strict type check might 1939 # claims that exceptions may be raised, or if a strict type check might
1934 # fail, or if we're dealing with SVG, which does strange things with 1940 # fail, or if we're dealing with SVG, which does strange things with
1935 # tearoffs and read-only wrappers. 1941 # tearoffs and read-only wrappers.
1936 if ($useExceptions or $hasStrictTypeChecking or GetSVGTypeNeedingTearOff($in terfaceName) or GetSVGTypeNeedingTearOff($attrType)) { 1942 if ($useExceptions or $hasStrictTypeChecking or GetSVGTypeNeedingTearOff($in terfaceName) or GetSVGTypeNeedingTearOff($attrType) or $isNumberType) {
1937 $code .= " ExceptionState exceptionState(ExceptionState::SetterContex t, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; 1943 $code .= " ExceptionState exceptionState(ExceptionState::SetterContex t, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
1938 } 1944 }
1939 1945
1940 # If the "StrictTypeChecking" extended attribute is present, and the 1946 # If the "StrictTypeChecking" extended attribute is present, and the
1941 # attribute's type is an interface type, then if the incoming value does not 1947 # attribute's type is an interface type, then if the incoming value does not
1942 # implement that interface, a TypeError is thrown rather than silently 1948 # implement that interface, a TypeError is thrown rather than silently
1943 # passing NULL to the C++ code. 1949 # passing NULL to the C++ code.
1944 # Per the Web IDL and ECMAScript specifications, incoming values can always 1950 # Per the Web IDL and ECMAScript specifications, incoming values can always
1945 # be converted to both strings and numbers, so do not throw TypeError if the 1951 # be converted to both strings and numbers, so do not throw TypeError if the
1946 # attribute is of these types. 1952 # attribute is of these types.
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
2353 # Append a number to an overloaded method's name to make it unique: 2359 # Append a number to an overloaded method's name to make it unique:
2354 $name = $name . $function->{overloadIndex}; 2360 $name = $name . $function->{overloadIndex};
2355 } 2361 }
2356 2362
2357 my $conditionalString = GenerateConditionalString($function); 2363 my $conditionalString = GenerateConditionalString($function);
2358 my $code = ""; 2364 my $code = "";
2359 $code .= "#if ${conditionalString}\n" if $conditionalString; 2365 $code .= "#if ${conditionalString}\n" if $conditionalString;
2360 $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionC allbackInfo<v8::Value>& info)\n"; 2366 $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionC allbackInfo<v8::Value>& info)\n";
2361 $code .= "{\n"; 2367 $code .= "{\n";
2362 2368
2363 # We throw exceptions using 'ExceptionState' if the function explicitly clai ms that exceptions 2369 # We throw exceptions using 'ExceptionState' for a function if:
2364 # may be raised, or for event listeners, or for security-checking, and for w eird SVG stuff. 2370 # - it explicitly claims that exceptions may be raised (or should be if ty pe checks fail.)
2371 # - event listeners.
2372 # - security-checking.
2373 # - weird SVG stuff.
2374 # - takes a parameter that might raise an exception on conversion.
2375 #
2365 my $isEventListener = $name eq "addEventListener" || $name eq "removeEventLi stener"; 2376 my $isEventListener = $name eq "addEventListener" || $name eq "removeEventLi stener";
2366 my $isSecurityCheckNecessary = $interface->extendedAttributes->{"CheckSecuri ty"} && !$function->extendedAttributes->{"DoNotCheckSecurity"}; 2377 my $isSecurityCheckNecessary = $interface->extendedAttributes->{"CheckSecuri ty"} && !$function->extendedAttributes->{"DoNotCheckSecurity"};
2367 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; 2378 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"};
2368 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty Types($interfaceName); 2379 my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGProperty Types($interfaceName);
2369 my $isNonListSVGType = $svgNativeType && !($interfaceName =~ /List$/); 2380 my $isNonListSVGType = $svgNativeType && !($interfaceName =~ /List$/);
2370 2381
2371 my $hasExceptionState = 0; 2382 my $hasExceptionState = $raisesExceptions || $isEventListener || $isSecurity CheckNecessary || $isNonListSVGType || HasExceptionRaisingParameter($function);
2372 if ($raisesExceptions || $isEventListener || $isSecurityCheckNecessary || $i sNonListSVGType || HasSerializedScriptValueParameter($function)) { 2383 if ($hasExceptionState) {
2373 $code .= " ExceptionState exceptionState(ExceptionState::ExecutionCon text, \"${unoverloadedName}\", \"${interfaceName}\", info.Holder(), info.GetIsol ate());\n"; 2384 $code .= " ExceptionState exceptionState(ExceptionState::ExecutionCon text, \"${unoverloadedName}\", \"${interfaceName}\", info.Holder(), info.GetIsol ate());\n";
2374 $hasExceptionState = 1;
2375 } 2385 }
2376 2386
2377 if ($isEventListener) { 2387 if ($isEventListener) {
2378 my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only"; 2388 my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only";
2379 my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()"; 2389 my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()";
2380 my $hiddenDependencyAction = ($name eq "addEventListener") ? "create" : "remove"; 2390 my $hiddenDependencyAction = ($name eq "addEventListener") ? "create" : "remove";
2381 2391
2382 AddToImplIncludes("bindings/v8/BindingSecurity.h"); 2392 AddToImplIncludes("bindings/v8/BindingSecurity.h");
2383 AddToImplIncludes("bindings/v8/V8EventListenerList.h"); 2393 AddToImplIncludes("bindings/v8/V8EventListenerList.h");
2384 AddToImplIncludes("core/frame/DOMWindow.h"); 2394 AddToImplIncludes("core/frame/DOMWindow.h");
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2452 $code .= " exceptionState.throwIfNeeded();\n"; 2462 $code .= " exceptionState.throwIfNeeded();\n";
2453 $code .= " return;\n"; 2463 $code .= " return;\n";
2454 $code .= " }\n"; 2464 $code .= " }\n";
2455 END 2465 END
2456 } 2466 }
2457 2467
2458 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, $forMainWorldSuffix, $hasExceptionState); 2468 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, $forMainWorldSuffix, $hasExceptionState);
2459 $code .= $parameterCheckString; 2469 $code .= $parameterCheckString;
2460 2470
2461 # Build the function call string. 2471 # Build the function call string.
2462 $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interfa ce, $forMainWorldSuffix, %replacements); 2472 $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interfa ce, $forMainWorldSuffix, $hasExceptionState, %replacements);
2463 $code .= "}\n"; 2473 $code .= "}\n";
2464 $code .= "#endif // ${conditionalString}\n" if $conditionalString; 2474 $code .= "#endif // ${conditionalString}\n" if $conditionalString;
2465 $code .= "\n"; 2475 $code .= "\n";
2466 $implementation{nameSpaceInternal}->add($code); 2476 $implementation{nameSpaceInternal}->add($code);
2467 } 2477 }
2468 2478
2469 sub GenerateCallWith 2479 sub GenerateCallWith
2470 { 2480 {
2471 my $callWith = shift; 2481 my $callWith = shift;
2472 return ([], "") unless $callWith; 2482 return ([], "") unless $callWith;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2560 foreach my $parameter (@{$function->parameters}) { 2570 foreach my $parameter (@{$function->parameters}) {
2561 my $humanFriendlyIndex = $paramIndex + 1; 2571 my $humanFriendlyIndex = $paramIndex + 1;
2562 my $nativeType = GetNativeType($parameter->type, $parameter->extendedAtt ributes, "parameter"); 2572 my $nativeType = GetNativeType($parameter->type, $parameter->extendedAtt ributes, "parameter");
2563 2573
2564 # Optional arguments without [Default=...] should generate an early call with fewer arguments. 2574 # Optional arguments without [Default=...] should generate an early call with fewer arguments.
2565 # Optional Dictionary arguments always considered to have default of emp ty dictionary. 2575 # Optional Dictionary arguments always considered to have default of emp ty dictionary.
2566 if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default "} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) { 2576 if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default "} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) {
2567 $parameterCheckString .= <<END; 2577 $parameterCheckString .= <<END;
2568 if (UNLIKELY(info.Length() <= $paramIndex)) { 2578 if (UNLIKELY(info.Length() <= $paramIndex)) {
2569 END 2579 END
2570 $parameterCheckString .= GenerateFunctionCallString($function, $para mIndex, " " x 2, $interface, $forMainWorldSuffix, %replacements); 2580 $parameterCheckString .= GenerateFunctionCallString($function, $para mIndex, " " x 2, $interface, $forMainWorldSuffix, $hasExceptionState, %replac ements);
2571 $parameterCheckString .= <<END; 2581 $parameterCheckString .= <<END;
2572 return; 2582 return;
2573 } 2583 }
2574 END 2584 END
2575 } 2585 }
2576 2586
2577 my $parameterName = $parameter->name; 2587 my $parameterName = $parameter->name;
2578 if (IsCallbackInterface($parameter->type)) { 2588 if (IsCallbackInterface($parameter->type)) {
2579 my $v8ClassName = "V8" . $parameter->type; 2589 my $v8ClassName = "V8" . $parameter->type;
2580 AddToImplIncludes("$v8ClassName.h"); 2590 AddToImplIncludes("$v8ClassName.h");
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
2771 2781
2772 my $interfaceName = $interface->name; 2782 my $interfaceName = $interface->name;
2773 my $implClassName = GetImplName($interface); 2783 my $implClassName = GetImplName($interface);
2774 my $v8ClassName = GetV8ClassName($interface); 2784 my $v8ClassName = GetV8ClassName($interface);
2775 my $overloadedIndexString = ""; 2785 my $overloadedIndexString = "";
2776 if ($function->overloadedIndex > 0) { 2786 if ($function->overloadedIndex > 0) {
2777 $overloadedIndexString .= $function->overloadedIndex; 2787 $overloadedIndexString .= $function->overloadedIndex;
2778 } 2788 }
2779 2789
2780 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor" ; 2790 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor" ;
2781 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"} || $constructorRaisesException || HasSerializedScriptValueParameter($function); 2791 my $hasExceptionState = $function->extendedAttributes->{"RaisesException"} | | $constructorRaisesException || HasExceptionRaisingParameter($function);
2782 2792
2783 my @beforeArgumentList; 2793 my @beforeArgumentList;
2784 my @afterArgumentList; 2794 my @afterArgumentList;
2785 my $code = ""; 2795 my $code = "";
2786 $code .= <<END; 2796 $code .= <<END;
2787 static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v 8::Value>& info) 2797 static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v 8::Value>& info)
2788 { 2798 {
2789 END 2799 END
2790 2800
2801 if ($hasExceptionState) {
2802 $code .= " ExceptionState exceptionState(ExceptionState::Construction Context, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
2803 }
2791 if ($function->overloadedIndex == 0) { 2804 if ($function->overloadedIndex == 0) {
2792 my $hasExceptionState = 0;
2793 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptio nState); 2805 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptio nState);
2794 } 2806 }
2795 2807
2796 if ($raisesExceptions) {
2797 $code .= " ExceptionState exceptionState(ExceptionState::Construction Context, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
2798 }
2799
2800 # FIXME: Currently [Constructor(...)] does not yet support optional argument s without [Default=...] 2808 # FIXME: Currently [Constructor(...)] does not yet support optional argument s without [Default=...]
2801 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, "", $raisesExceptions); 2809 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, "", $hasExceptionState);
2802 $code .= $parameterCheckString; 2810 $code .= $parameterCheckString;
2803 2811
2804 if ($interface->extendedAttributes->{"ConstructorCallWith"}) { 2812 if ($interface->extendedAttributes->{"ConstructorCallWith"}) {
2805 if (ExtendedAttributeContains($interface->extendedAttributes->{"Construc torCallWith"}, "ExecutionContext")) { 2813 if (ExtendedAttributeContains($interface->extendedAttributes->{"Construc torCallWith"}, "ExecutionContext")) {
2806 push(@beforeArgumentList, "context"); 2814 push(@beforeArgumentList, "context");
2807 $code .= " ExecutionContext* context = getExecutionContext();\n"; 2815 $code .= " ExecutionContext* context = getExecutionContext();\n";
2808 } 2816 }
2809 if (ExtendedAttributeContains($interface->extendedAttributes->{"Construc torCallWith"}, "Document")) { 2817 if (ExtendedAttributeContains($interface->extendedAttributes->{"Construc torCallWith"}, "Document")) {
2810 push(@beforeArgumentList, "document"); 2818 push(@beforeArgumentList, "document");
2811 $code .= " Document& document = *toDocument(getExecutionContext() );\n"; 2819 $code .= " Document& document = *toDocument(getExecutionContext() );\n";
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
3065 3073
3066 sub GenerateNamedConstructor 3074 sub GenerateNamedConstructor
3067 { 3075 {
3068 my $function = shift; 3076 my $function = shift;
3069 my $interface = shift; 3077 my $interface = shift;
3070 3078
3071 my $interfaceName = $interface->name; 3079 my $interfaceName = $interface->name;
3072 my $implClassName = GetImplName($interface); 3080 my $implClassName = GetImplName($interface);
3073 my $v8ClassName = GetV8ClassName($interface); 3081 my $v8ClassName = GetV8ClassName($interface);
3074 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor" ; 3082 my $constructorRaisesException = $interface->extendedAttributes->{"RaisesExc eption"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor" ;
3075 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"} || $constructorRaisesException || HasSerializedScriptValueParameter($function); 3083 my $raisesExceptions = $function->extendedAttributes->{"RaisesException"} || $constructorRaisesException || HasExceptionRaisingParameter($function);
3076 3084
3077 my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttr ibutes->{"MeasureAs"}); 3085 my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttr ibutes->{"MeasureAs"});
3078 my $maybeDeprecateFeature = GenerateDeprecationNotification($function->exten dedAttributes->{"DeprecateAs"}); 3086 my $maybeDeprecateFeature = GenerateDeprecationNotification($function->exten dedAttributes->{"DeprecateAs"});
3079 3087
3080 my @beforeArgumentList; 3088 my @beforeArgumentList;
3081 my @afterArgumentList; 3089 my @afterArgumentList;
3082 3090
3083 my $toActiveDOMObject = "0"; 3091 my $toActiveDOMObject = "0";
3084 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { 3092 if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) {
3085 $toActiveDOMObject = "${v8ClassName}::toActiveDOMObject"; 3093 $toActiveDOMObject = "${v8ClassName}::toActiveDOMObject";
(...skipping 20 matching lines...) Expand all
3106 $code .= <<END; 3114 $code .= <<END;
3107 Document* document = currentDocument(); 3115 Document* document = currentDocument();
3108 ASSERT(document); 3116 ASSERT(document);
3109 3117
3110 // Make sure the document is added to the DOM Node map. Otherwise, the ${imp lClassName} instance 3118 // Make sure the document is added to the DOM Node map. Otherwise, the ${imp lClassName} instance
3111 // may end up being the only node in the map and get garbage-collected prema turely. 3119 // may end up being the only node in the map and get garbage-collected prema turely.
3112 toV8(document, info.Holder(), info.GetIsolate()); 3120 toV8(document, info.Holder(), info.GetIsolate());
3113 3121
3114 END 3122 END
3115 3123
3116 if ($raisesExceptions) { 3124 my $hasExceptionState = $raisesExceptions;
3125 if ($hasExceptionState) {
3117 $code .= " ExceptionState exceptionState(ExceptionState::Construction Context, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; 3126 $code .= " ExceptionState exceptionState(ExceptionState::Construction Context, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n";
3118 } 3127 }
3119
3120 my $hasExceptionState = $raisesExceptions;
3121 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionSta te); 3128 $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionSta te);
3122 3129
3123 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, "", $raisesExceptions); 3130 my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersC heck($function, $interface, "", $hasExceptionState);
3124 $code .= $parameterCheckString; 3131 $code .= $parameterCheckString;
3125 3132
3126 push(@beforeArgumentList, "*document"); 3133 push(@beforeArgumentList, "*document");
3127 3134
3128 if ($constructorRaisesException) { 3135 if ($constructorRaisesException) {
3129 push(@afterArgumentList, "exceptionState"); 3136 push(@afterArgumentList, "exceptionState");
3130 } 3137 }
3131 3138
3132 my @argumentList; 3139 my @argumentList;
3133 my $index = 0; 3140 my $index = 0;
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
3700 $implementation{nameSpaceInternal}->add($code); 3707 $implementation{nameSpaceInternal}->add($code);
3701 } 3708 }
3702 3709
3703 sub GenerateImplementationIndexedPropertySetter 3710 sub GenerateImplementationIndexedPropertySetter
3704 { 3711 {
3705 my $interface = shift; 3712 my $interface = shift;
3706 my $indexedSetterFunction = shift; 3713 my $indexedSetterFunction = shift;
3707 my $implClassName = GetImplName($interface); 3714 my $implClassName = GetImplName($interface);
3708 my $v8ClassName = GetV8ClassName($interface); 3715 my $v8ClassName = GetV8ClassName($interface);
3709 my $methodName = GetImplName($indexedSetterFunction); 3716 my $methodName = GetImplName($indexedSetterFunction);
3717 my $interfaceName = $interface->name;
3710 3718
3711 my $type = $indexedSetterFunction->parameters->[1]->type; 3719 my $type = $indexedSetterFunction->parameters->[1]->type;
3712 my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesE xception"}; 3720 my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesE xception"};
3713 my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttribute s->{"TreatNullAs"}; 3721 my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttribute s->{"TreatNullAs"};
3714 my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttr ibutes->{"TreatUndefinedAs"}; 3722 my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttr ibutes->{"TreatUndefinedAs"};
3715 my $asSetterValue = 0;
3716 3723
3717 my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8:: Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; 3724 my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8:: Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
3718 $code .= "{\n"; 3725 $code .= "{\n";
3726
3727 my $extraArguments = "";
3728 if ($raisesExceptions || IsIntegerType($type)) {
3729 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsola te());\n";
3730 if ($raisesExceptions) {
3731 $extraArguments = ", exceptionState";
3732 }
3733 }
3734
3735 my $asSetterValue = 0;
3719 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n"; 3736 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n";
3720 $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->t ype, $indexedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "pro pertyValue", " ", "info.GetIsolate()"); 3737 $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->t ype, $indexedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "pro pertyValue", " ", "info.GetIsolate()");
3721 3738
3722 my $extraArguments = "";
3723 if ($raisesExceptions) {
3724 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsola te());\n";
3725 $extraArguments = ", exceptionState";
3726 }
3727 my @conditions = (); 3739 my @conditions = ();
3728 my @statements = (); 3740 my @statements = ();
3729 if ($treatNullAs && $treatNullAs ne "NullString") { 3741 if ($treatNullAs && $treatNullAs ne "NullString") {
3730 push @conditions, "jsValue->IsNull()"; 3742 push @conditions, "jsValue->IsNull()";
3731 push @statements, "collection->${treatNullAs}(index$extraArguments);"; 3743 push @statements, "collection->${treatNullAs}(index$extraArguments);";
3732 } 3744 }
3733 if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") { 3745 if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") {
3734 push @conditions, "jsValue->IsUndefined()"; 3746 push @conditions, "jsValue->IsUndefined()";
3735 push @statements, "collection->${treatUndefinedAs}(index$extraArguments) ;"; 3747 push @statements, "collection->${treatUndefinedAs}(index$extraArguments) ;";
3736 } 3748 }
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
4005 $implementation{nameSpaceInternal}->add($code); 4017 $implementation{nameSpaceInternal}->add($code);
4006 } 4018 }
4007 4019
4008 sub GenerateImplementationNamedPropertySetter 4020 sub GenerateImplementationNamedPropertySetter
4009 { 4021 {
4010 my $interface = shift; 4022 my $interface = shift;
4011 my $namedSetterFunction = shift; 4023 my $namedSetterFunction = shift;
4012 my $implClassName = GetImplName($interface); 4024 my $implClassName = GetImplName($interface);
4013 my $v8ClassName = GetV8ClassName($interface); 4025 my $v8ClassName = GetV8ClassName($interface);
4014 my $methodName = GetImplName($namedSetterFunction); 4026 my $methodName = GetImplName($namedSetterFunction);
4027 my $interfaceName = $interface->name;
4015 4028
4029 my $type = $namedSetterFunction->parameters->[1]->type;
4016 my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesExc eption"}; 4030 my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesExc eption"};
4017 my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes- >{"TreatNullAs"}; 4031 my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes- >{"TreatNullAs"};
4018 my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttrib utes->{"TreatUndefinedAs"}; 4032 my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttrib utes->{"TreatUndefinedAs"};
4019 my $asSetterValue = 0;
4020 4033
4021 my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8:: Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; 4034 my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8:: Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n";
4022 $code .= "{\n"; 4035 $code .= "{\n";
4023 if (!$namedSetterFunction->extendedAttributes->{"OverrideBuiltins"}) { 4036 if (!$namedSetterFunction->extendedAttributes->{"OverrideBuiltins"}) {
4024 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n ame).IsEmpty())\n"; 4037 $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(n ame).IsEmpty())\n";
4025 $code .= " return;\n"; 4038 $code .= " return;\n";
4026 $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n"; 4039 $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n";
4027 $code .= " return;\n"; 4040 $code .= " return;\n";
4028 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; 4041 $code .= " if (info.Holder()->HasRealNamedProperty(name))\n";
4029 $code .= " return;\n"; 4042 $code .= " return;\n";
4030 } 4043 }
4044
4045 my $extraArguments = "";
4046 if ($raisesExceptions || IsIntegerType($type)) {
4047 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsola te());\n";
4048 if ($raisesExceptions) {
4049 $extraArguments = ", exceptionState";
4050 }
4051 }
4052
4053 my $asSetterValue = 0;
4031 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n"; 4054 $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.H older());\n";
4032 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->typ e, $namedSetterFunction->extendedAttributes, $asSetterValue, "name", "propertyNa me", " ", "info.GetIsolate()"); 4055 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->typ e, $namedSetterFunction->extendedAttributes, $asSetterValue, "name", "propertyNa me", " ", "info.GetIsolate()");
4033 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->typ e, $namedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "propert yValue", " ", "info.GetIsolate()"); 4056 $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->typ e, $namedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "propert yValue", " ", "info.GetIsolate()");
4034 my $extraArguments = "";
4035 if ($raisesExceptions) {
4036 $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsola te());\n";
4037 $extraArguments = ", exceptionState";
4038 }
4039 4057
4040 my @conditions = (); 4058 my @conditions = ();
4041 my @statements = (); 4059 my @statements = ();
4042 if ($treatNullAs && $treatNullAs ne "NullString") { 4060 if ($treatNullAs && $treatNullAs ne "NullString") {
4043 push @conditions, "jsValue->IsNull()"; 4061 push @conditions, "jsValue->IsNull()";
4044 push @statements, "collection->${treatNullAs}(propertyName$extraArgument s);"; 4062 push @statements, "collection->${treatNullAs}(propertyName$extraArgument s);";
4045 } 4063 }
4046 if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") { 4064 if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") {
4047 push @conditions, "jsValue->IsUndefined()"; 4065 push @conditions, "jsValue->IsUndefined()";
4048 push @statements, "collection->${treatUndefinedAs}(propertyName$extraArg uments);"; 4066 push @statements, "collection->${treatUndefinedAs}(propertyName$extraArg uments);";
(...skipping 1131 matching lines...) Expand 10 before | Expand all | Expand 10 after
5180 return "WebCore"; 5198 return "WebCore";
5181 } 5199 }
5182 5200
5183 sub GenerateFunctionCallString 5201 sub GenerateFunctionCallString
5184 { 5202 {
5185 my $function = shift; 5203 my $function = shift;
5186 my $numberOfParameters = shift; 5204 my $numberOfParameters = shift;
5187 my $indent = shift; 5205 my $indent = shift;
5188 my $interface = shift; 5206 my $interface = shift;
5189 my $forMainWorldSuffix = shift; 5207 my $forMainWorldSuffix = shift;
5208 my $hasExceptionState = shift;
5190 my %replacements = @_; 5209 my %replacements = @_;
5191 5210
5192 my $interfaceName = $interface->name; 5211 my $interfaceName = $interface->name;
5193 my $implClassName = GetImplName($interface); 5212 my $implClassName = GetImplName($interface);
5194 my $name = GetImplName($function); 5213 my $name = GetImplName($function);
5195 my $returnType = $function->type; 5214 my $returnType = $function->type;
5196 my $nativeReturnType = GetNativeType($returnType, {}, ""); 5215 my $nativeReturnType = GetNativeType($returnType, {}, "");
5197 my $code = ""; 5216 my $code = "";
5198 5217
5199 my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interf aceName =~ /List$/); 5218 my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interf aceName =~ /List$/);
(...skipping 29 matching lines...) Expand all
5229 if ($index eq $numberOfParameters) { 5248 if ($index eq $numberOfParameters) {
5230 last; 5249 last;
5231 } 5250 }
5232 my $paramName = $parameter->name; 5251 my $paramName = $parameter->name;
5233 my $paramType = $parameter->type; 5252 my $paramType = $parameter->type;
5234 5253
5235 if ($replacements{$paramName}) { 5254 if ($replacements{$paramName}) {
5236 push @arguments, $replacements{$paramName}; 5255 push @arguments, $replacements{$paramName};
5237 } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceNam e =~ /List$/) { 5256 } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceNam e =~ /List$/) {
5238 push @arguments, "$paramName->propertyReference()"; 5257 push @arguments, "$paramName->propertyReference()";
5239 $code .= <<END; 5258 if ($hasExceptionState) {
5259 $code .= <<END;
5260 if (!$paramName) {
5261 exceptionState.throwTypeError(\"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }'.\");
5262 exceptionState.throwIfNeeded();
5263 return;
5264 }
5265 END
5266 } else {
5267 $code .= <<END;
5240 if (!$paramName) { 5268 if (!$paramName) {
5241 throwTypeError(ExceptionMessages::failedToExecute(\"$name\", \"$interfac eName\", \"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }' .\"), info.GetIsolate()); 5269 throwTypeError(ExceptionMessages::failedToExecute(\"$name\", \"$interfac eName\", \"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }' .\"), info.GetIsolate());
5242 return; 5270 return;
5243 } 5271 }
5244 END 5272 END
5273 }
5245 } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTrans formList") { 5274 } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTrans formList") {
5246 push @arguments, "$paramName.get()"; 5275 push @arguments, "$paramName.get()";
5247 } elsif (IsNullableParameter($parameter)) { 5276 } elsif (IsNullableParameter($parameter)) {
5248 push @arguments, "${paramName}IsNull ? 0 : &$paramName"; 5277 push @arguments, "${paramName}IsNull ? 0 : &$paramName";
5249 } elsif (IsCallbackInterface($paramType) or $paramType eq "NodeFilter" o r $paramType eq "XPathNSResolver") { 5278 } elsif (IsCallbackInterface($paramType) or $paramType eq "NodeFilter" o r $paramType eq "XPathNSResolver") {
5250 push @arguments, "$paramName.release()"; 5279 push @arguments, "$paramName.release()";
5251 } else { 5280 } else {
5252 push @arguments, $paramName; 5281 push @arguments, $paramName;
5253 } 5282 }
5254 $index++; 5283 $index++;
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
5423 my $nativeType = GetNativeType($type, $extendedAttributes, "parameter"); 5452 my $nativeType = GetNativeType($type, $extendedAttributes, "parameter");
5424 my $native_value = JSValueToNative($type, $extendedAttributes, $argIndexOrZe ro, $jsValue, $getIsolate); 5453 my $native_value = JSValueToNative($type, $extendedAttributes, $argIndexOrZe ro, $jsValue, $getIsolate);
5425 my $code = ""; 5454 my $code = "";
5426 if ($type eq "DOMString" || IsEnumType($type)) { 5455 if ($type eq "DOMString" || IsEnumType($type)) {
5427 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8St ringResource/; 5456 die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8St ringResource/;
5428 if ($type eq "DOMString" or IsEnumType($type)) { 5457 if ($type eq "DOMString" or IsEnumType($type)) {
5429 $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType , $variableName, $native_value);\n" 5458 $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType , $variableName, $native_value);\n"
5430 } else { 5459 } else {
5431 $code .= $indent . "$nativeType $variableName($native_value, true);\ n"; 5460 $code .= $indent . "$nativeType $variableName($native_value, true);\ n";
5432 } 5461 }
5433 } elsif ($extendedAttributes->{"EnforceRange"}) { 5462 } elsif (IsIntegerType($type)) {
5434 $code .= $indent . "V8TRYCATCH_WITH_TYPECHECK_VOID($nativeType, $variabl eName, $native_value, $getIsolate);\n"; 5463 $code .= $indent . "V8TRYCATCH_EXCEPTION_VOID($nativeType, $variableName , $native_value, exceptionState);\n";
5435 } else { 5464 } else {
5436 $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_ value);\n"; 5465 $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_ value);\n";
5437 } 5466 }
5438 return $code; 5467 return $code;
5439 } 5468 }
5440 5469
5441 5470
5442 sub JSValueToNative 5471 sub JSValueToNative
5443 { 5472 {
5444 my $type = shift; 5473 my $type = shift;
5445 my $extendedAttributes = shift; 5474 my $extendedAttributes = shift;
5446 # Argument position (1-indexed) or 0 if for a setter's value. 5475 # Argument position (1-indexed) or 0 if for a setter's value.
5447 my $argIndexOrZero = shift; 5476 my $argIndexOrZero = shift;
5448 my $value = shift; 5477 my $value = shift;
5449 my $getIsolate = shift; 5478 my $getIsolate = shift;
5450 5479
5451 my $intConversion = $extendedAttributes->{"EnforceRange"} ? "EnforceRange" : "NormalConversion";
5452
5453 return "$value->BooleanValue()" if $type eq "boolean"; 5480 return "$value->BooleanValue()" if $type eq "boolean";
5454 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $t ype eq "double"; 5481 return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $t ype eq "double";
5455 5482
5456 if ($intConversion ne "NormalConversion") { 5483 if (IsIntegerType($type)) {
5457 return "toInt8($value, $intConversion, ok)" if $type eq "byte"; 5484 my $conversion = "to" . $integerTypeHash{$type} . "($value";
5458 return "toUInt8($value, $intConversion, ok)" if $type eq "octet"; 5485 if ($extendedAttributes->{"EnforceRange"}) {
5459 return "toInt16($value, $intConversion, ok)" if $type eq "short"; 5486 return "${conversion}, EnforceRange, exceptionState)";
5460 return "toUInt16($value, $intConversion, ok)" if $type eq "unsigned shor t"; 5487 } else {
5461 return "toInt32($value, $intConversion, ok)" if $type eq "long"; 5488 return "${conversion}, exceptionState)";
5462 return "toUInt32($value, $intConversion, ok)" if $type eq "unsigned long "; 5489 }
5463 return "toInt64($value, $intConversion, ok)" if $type eq "long long";
5464 return "toUInt64($value, $intConversion, ok)" if $type eq "unsigned long long";
5465 } else {
5466 return "toInt8($value)" if $type eq "byte";
5467 return "toUInt8($value)" if $type eq "octet";
5468 return "toInt16($value)" if $type eq "short";
5469 return "toUInt16($value)" if $type eq "unsigned short";
5470 return "toInt32($value)" if $type eq "long";
5471 return "toUInt32($value)" if $type eq "unsigned long";
5472 return "toInt64($value)" if $type eq "long long";
5473 return "toUInt64($value)" if $type eq "unsigned long long";
5474 } 5490 }
5475 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "C ompareHow"; 5491 return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "C ompareHow";
5476 return "toWebCoreDate($value)" if $type eq "Date"; 5492 return "toWebCoreDate($value)" if $type eq "Date";
5477 5493
5478 if ($type eq "DOMString" or IsEnumType($type)) { 5494 if ($type eq "DOMString" or IsEnumType($type)) {
5479 return $value; 5495 return $value;
5480 } 5496 }
5481 5497
5482 if ($type eq "SerializedScriptValue") { 5498 if ($type eq "SerializedScriptValue") {
5483 AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); 5499 AddToImplIncludes("bindings/v8/SerializedScriptValue.h");
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after
6369 my $interface = shift; 6385 my $interface = shift;
6370 6386
6371 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Cust om"}, "ToV8"); 6387 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Cust om"}, "ToV8");
6372 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Cust om"}, "Wrap"); 6388 return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Cust om"}, "Wrap");
6373 return 1 if $interface->extendedAttributes->{"SpecialWrapFor"}; 6389 return 1 if $interface->extendedAttributes->{"SpecialWrapFor"};
6374 return 1 if InheritsInterface($interface, "Document"); 6390 return 1 if InheritsInterface($interface, "Document");
6375 6391
6376 return 0; 6392 return 0;
6377 } 6393 }
6378 6394
6379 sub HasSerializedScriptValueParameter 6395 sub HasExceptionRaisingParameter
6380 { 6396 {
6381 my $function = shift; 6397 my $function = shift;
6382 6398
6383 foreach my $parameter (@{$function->parameters}) { 6399 foreach my $parameter (@{$function->parameters}) {
6384 if ($parameter->type eq "SerializedScriptValue") { 6400 if ($parameter->type eq "SerializedScriptValue") {
6385 return 1; 6401 return 1;
6402 } elsif (IsIntegerType($parameter->type)) {
6403 return 1;
6386 } 6404 }
6387 } 6405 }
6388 return 0; 6406 return 0;
6389 } 6407 }
6390 6408
6391 1; 6409 1;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698