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

Side by Side Diff: Source/bindings/tests/results/V8TestInterfaceNamedConstructor.cpp

Issue 116153002: IDL compiler: [NamedConstructor] (basic) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 // This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY! 31 // This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY!
32 32
33 #include "config.h" 33 #include "config.h"
34 #include "V8TestNamedConstructor.h" 34 #include "V8TestInterfaceNamedConstructor.h"
35 35
36 #include "RuntimeEnabledFeatures.h" 36 #include "RuntimeEnabledFeatures.h"
37 #include "V8Document.h" 37 #include "V8Document.h"
38 #include "bindings/v8/ExceptionState.h" 38 #include "bindings/v8/ExceptionState.h"
39 #include "bindings/v8/V8DOMConfiguration.h" 39 #include "bindings/v8/V8DOMConfiguration.h"
40 #include "bindings/v8/V8ObjectConstructor.h" 40 #include "bindings/v8/V8ObjectConstructor.h"
41 #include "core/dom/ContextFeatures.h" 41 #include "core/dom/ContextFeatures.h"
42 #include "core/dom/Document.h" 42 #include "core/dom/Document.h"
43 #include "platform/TraceEvent.h" 43 #include "platform/TraceEvent.h"
44 44
45 namespace WebCore { 45 namespace WebCore {
46 46
47 static void initializeScriptWrappableForInterface(TestNamedConstructor* object) 47 static void initializeScriptWrappableForInterface(TestInterfaceNamedConstructor* object)
48 { 48 {
49 if (ScriptWrappable::wrapperCanBeStoredInObject(object)) 49 if (ScriptWrappable::wrapperCanBeStoredInObject(object))
50 ScriptWrappable::setTypeInfoInObject(object, &V8TestNamedConstructor::wr apperTypeInfo); 50 ScriptWrappable::setTypeInfoInObject(object, &V8TestInterfaceNamedConstr uctor::wrapperTypeInfo);
51 else 51 else
52 ASSERT_NOT_REACHED(); 52 ASSERT_NOT_REACHED();
53 } 53 }
54 54
55 } // namespace WebCore 55 } // namespace WebCore
56 56
57 // In ScriptWrappable::init, the use of a local function declaration has an issu e on Windows: 57 // In ScriptWrappable::init, the use of a local function declaration has an issu e on Windows:
58 // the local declaration does not pick up the surrounding namespace. Therefore, we provide this function 58 // the local declaration does not pick up the surrounding namespace. Therefore, we provide this function
59 // in the global namespace. 59 // in the global namespace.
60 // (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/fe edback/details/664619/the-namespace-of-local-function-declarations-in-c) 60 // (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/fe edback/details/664619/the-namespace-of-local-function-declarations-in-c)
61 void webCoreInitializeScriptWrappableForInterface(WebCore::TestNamedConstructor* object) 61 void webCoreInitializeScriptWrappableForInterface(WebCore::TestInterfaceNamedCon structor* object)
62 { 62 {
63 WebCore::initializeScriptWrappableForInterface(object); 63 WebCore::initializeScriptWrappableForInterface(object);
64 } 64 }
65 65
66 namespace WebCore { 66 namespace WebCore {
67 const WrapperTypeInfo V8TestNamedConstructor::wrapperTypeInfo = { gin::kEmbedder Blink, V8TestNamedConstructor::domTemplate, V8TestNamedConstructor::derefObject, V8TestNamedConstructor::toActiveDOMObject, 0, 0, V8TestNamedConstructor::instal lPerContextEnabledMethods, 0, WrapperTypeObjectPrototype }; 67 const WrapperTypeInfo V8TestInterfaceNamedConstructor::wrapperTypeInfo = { gin:: kEmbedderBlink, V8TestInterfaceNamedConstructor::domTemplate, V8TestInterfaceNam edConstructor::derefObject, 0, 0, 0, V8TestInterfaceNamedConstructor::installPer ContextEnabledMethods, 0, WrapperTypeObjectPrototype };
68 68
69 namespace TestNamedConstructorV8Internal { 69 namespace TestInterfaceNamedConstructorV8Internal {
70 70
71 template <typename T> void V8_USE(T) { } 71 template <typename T> void V8_USE(T) { }
72 72
73 } // namespace TestNamedConstructorV8Internal 73 } // namespace TestInterfaceNamedConstructorV8Internal
74 74
75 const WrapperTypeInfo V8TestNamedConstructorConstructor::wrapperTypeInfo = { gin ::kEmbedderBlink, V8TestNamedConstructorConstructor::domTemplate, V8TestNamedCon structor::derefObject, V8TestNamedConstructor::toActiveDOMObject, 0, 0, V8TestNa medConstructor::installPerContextEnabledMethods, 0, WrapperTypeObjectPrototype } ; 75 const WrapperTypeInfo V8TestInterfaceNamedConstructorConstructor::wrapperTypeInf o = { gin::kEmbedderBlink, V8TestInterfaceNamedConstructorConstructor::domTempla te, V8TestInterfaceNamedConstructor::derefObject, 0, 0, 0, V8TestInterfaceNamedC onstructor::installPerContextEnabledMethods, 0, WrapperTypeObjectPrototype };
76 76
77 static void V8TestNamedConstructorConstructorCallback(const v8::FunctionCallback Info<v8::Value>& info) 77 static void V8TestInterfaceNamedConstructorConstructorCallback(const v8::Functio nCallbackInfo<v8::Value>& info)
78 { 78 {
79 if (!info.IsConstructCall()) { 79 if (!info.IsConstructCall()) {
80 throwTypeError(ExceptionMessages::failedToConstruct("Audio", "Please use the 'new' operator, this DOM object constructor cannot be called as a function. "), info.GetIsolate()); 80 throwTypeError(ExceptionMessages::failedToConstruct("Audio", "Please use the 'new' operator, this DOM object constructor cannot be called as a function. "), info.GetIsolate());
81 return; 81 return;
82 } 82 }
83 83
84 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { 84 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
85 v8SetReturnValue(info, info.Holder()); 85 v8SetReturnValue(info, info.Holder());
86 return; 86 return;
87 } 87 }
88 88
89 Document* document = currentDocument(); 89 Document* document = currentDocument();
90 ASSERT(document); 90 ASSERT(document);
91 91
92 // Make sure the document is added to the DOM Node map. Otherwise, the TestN amedConstructor instance 92 // Make sure the document is added to the DOM Node map. Otherwise, the TestI nterfaceNamedConstructor instance
93 // may end up being the only node in the map and get garbage-collected prema turely. 93 // may end up being the only node in the map and get garbage-collected prema turely.
94 toV8(document, info.Holder(), info.GetIsolate()); 94 toV8(document, info.Holder(), info.GetIsolate());
95 95
96 ExceptionState exceptionState(ExceptionState::ConstructionContext, "TestName dConstructor", info.Holder(), info.GetIsolate()); 96 RefPtr<TestInterfaceNamedConstructor> impl = TestInterfaceNamedConstructor:: createForJSConstructor(*document);
97 if (UNLIKELY(info.Length() < 1)) { 97 v8::Handle<v8::Object> wrapper = info.Holder();
98 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, i nfo.Length()));
99 exceptionState.throwIfNeeded();
100 return;
101 }
102 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, str1, info[0]);
103 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, str2, info[1]);
104 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, str3, argumentOrNul l(info, 2));
105 98
106 RefPtr<TestNamedConstructor> impl = TestNamedConstructor::createForJSConstru ctor(*document, str1, str2, str3, exceptionState); 99 V8DOMWrapper::associateObjectWithWrapper<V8TestInterfaceNamedConstructor>(im pl.release(), &V8TestInterfaceNamedConstructorConstructor::wrapperTypeInfo, wrap per, info.GetIsolate(), WrapperConfiguration::Dependent);
107 v8::Handle<v8::Object> wrapper = info.Holder();
108 if (exceptionState.throwIfNeeded())
109 return;
110
111 V8DOMWrapper::associateObjectWithWrapper<V8TestNamedConstructor>(impl.releas e(), &V8TestNamedConstructorConstructor::wrapperTypeInfo, wrapper, info.GetIsola te(), WrapperConfiguration::Dependent);
112 v8SetReturnValue(info, wrapper); 100 v8SetReturnValue(info, wrapper);
113 } 101 }
114 102
115 v8::Handle<v8::FunctionTemplate> V8TestNamedConstructorConstructor::domTemplate( v8::Isolate* isolate, WrapperWorldType currentWorldType) 103 v8::Handle<v8::FunctionTemplate> V8TestInterfaceNamedConstructorConstructor::dom Template(v8::Isolate* isolate, WrapperWorldType currentWorldType)
116 { 104 {
117 // This is only for getting a unique pointer which we can pass to privateTem plate. 105 // This is only for getting a unique pointer which we can pass to privateTem plate.
118 static int privateTemplateUniqueKey; 106 static int privateTemplateUniqueKey;
119 V8PerIsolateData* data = V8PerIsolateData::from(isolate); 107 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
120 v8::Local<v8::FunctionTemplate> result = data->privateTemplateIfExists(curre ntWorldType, &privateTemplateUniqueKey); 108 v8::Local<v8::FunctionTemplate> result = data->privateTemplateIfExists(curre ntWorldType, &privateTemplateUniqueKey);
121 if (!result.IsEmpty()) 109 if (!result.IsEmpty())
122 return result; 110 return result;
123 111
124 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); 112 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
125 v8::EscapableHandleScope scope(isolate); 113 v8::EscapableHandleScope scope(isolate);
126 result = v8::FunctionTemplate::New(isolate, V8TestNamedConstructorConstructo rCallback); 114 result = v8::FunctionTemplate::New(isolate, V8TestInterfaceNamedConstructorC onstructorCallback);
127 115
128 v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate(); 116 v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate();
129 instanceTemplate->SetInternalFieldCount(V8TestNamedConstructor::internalFiel dCount); 117 instanceTemplate->SetInternalFieldCount(V8TestInterfaceNamedConstructor::int ernalFieldCount);
130 result->SetClassName(v8::String::NewFromUtf8(isolate, "TestNamedConstructor" , v8::String::kInternalizedString)); 118 result->SetClassName(v8::String::NewFromUtf8(isolate, "TestInterfaceNamedCon structor", v8::String::kInternalizedString));
131 result->Inherit(V8TestNamedConstructor::domTemplate(isolate, currentWorldTyp e)); 119 result->Inherit(V8TestInterfaceNamedConstructor::domTemplate(isolate, curren tWorldType));
132 data->setPrivateTemplate(currentWorldType, &privateTemplateUniqueKey, result ); 120 data->setPrivateTemplate(currentWorldType, &privateTemplateUniqueKey, result );
133 121
134 return scope.Escape(result); 122 return scope.Escape(result);
135 } 123 }
136 124
137 static v8::Handle<v8::FunctionTemplate> ConfigureV8TestNamedConstructorTemplate( v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate, Wrapper WorldType currentWorldType) 125 static v8::Handle<v8::FunctionTemplate> ConfigureV8TestInterfaceNamedConstructor Template(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate , WrapperWorldType currentWorldType)
138 { 126 {
139 functionTemplate->ReadOnlyPrototype(); 127 functionTemplate->ReadOnlyPrototype();
140 128
141 v8::Local<v8::Signature> defaultSignature; 129 v8::Local<v8::Signature> defaultSignature;
142 defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTempl ate, "TestNamedConstructor", v8::Local<v8::FunctionTemplate>(), V8TestNamedConst ructor::internalFieldCount, 130 defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTempl ate, "TestInterfaceNamedConstructor", v8::Local<v8::FunctionTemplate>(), V8TestI nterfaceNamedConstructor::internalFieldCount,
143 0, 0, 131 0, 0,
144 0, 0, 132 0, 0,
145 0, 0, 133 0, 0,
146 isolate, currentWorldType); 134 isolate, currentWorldType);
147 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED instanceTemplate = functionTempla te->InstanceTemplate(); 135 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED instanceTemplate = functionTempla te->InstanceTemplate();
148 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED prototypeTemplate = functionTempl ate->PrototypeTemplate(); 136 v8::Local<v8::ObjectTemplate> ALLOW_UNUSED prototypeTemplate = functionTempl ate->PrototypeTemplate();
149 137
150 // Custom toString template 138 // Custom toString template
151 functionTemplate->Set(v8::String::NewFromUtf8(isolate, "toString", v8::Strin g::kInternalizedString), V8PerIsolateData::current()->toStringTemplate()); 139 functionTemplate->Set(v8::String::NewFromUtf8(isolate, "toString", v8::Strin g::kInternalizedString), V8PerIsolateData::current()->toStringTemplate());
152 return functionTemplate; 140 return functionTemplate;
153 } 141 }
154 142
155 v8::Handle<v8::FunctionTemplate> V8TestNamedConstructor::domTemplate(v8::Isolate * isolate, WrapperWorldType currentWorldType) 143 v8::Handle<v8::FunctionTemplate> V8TestInterfaceNamedConstructor::domTemplate(v8 ::Isolate* isolate, WrapperWorldType currentWorldType)
156 { 144 {
157 V8PerIsolateData* data = V8PerIsolateData::from(isolate); 145 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
158 V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWo rldType).find(&wrapperTypeInfo); 146 V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWo rldType).find(&wrapperTypeInfo);
159 if (result != data->templateMap(currentWorldType).end()) 147 if (result != data->templateMap(currentWorldType).end())
160 return result->value.newLocal(isolate); 148 return result->value.newLocal(isolate);
161 149
162 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); 150 TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate");
163 v8::EscapableHandleScope handleScope(isolate); 151 v8::EscapableHandleScope handleScope(isolate);
164 v8::Local<v8::FunctionTemplate> templ = 152 v8::Local<v8::FunctionTemplate> templ =
165 ConfigureV8TestNamedConstructorTemplate(data->rawDOMTemplate(&wrapperTyp eInfo, currentWorldType), isolate, currentWorldType); 153 ConfigureV8TestInterfaceNamedConstructorTemplate(data->rawDOMTemplate(&w rapperTypeInfo, currentWorldType), isolate, currentWorldType);
166 data->templateMap(currentWorldType).add(&wrapperTypeInfo, UnsafePersistent<v 8::FunctionTemplate>(isolate, templ)); 154 data->templateMap(currentWorldType).add(&wrapperTypeInfo, UnsafePersistent<v 8::FunctionTemplate>(isolate, templ));
167 return handleScope.Escape(templ); 155 return handleScope.Escape(templ);
168 } 156 }
169 157
170 bool V8TestNamedConstructor::hasInstance(v8::Handle<v8::Value> jsValue, v8::Isol ate* isolate, WrapperWorldType currentWorldType) 158 bool V8TestInterfaceNamedConstructor::hasInstance(v8::Handle<v8::Value> jsValue, v8::Isolate* isolate, WrapperWorldType currentWorldType)
171 { 159 {
172 return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e, currentWorldType); 160 return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e, currentWorldType);
173 } 161 }
174 162
175 bool V8TestNamedConstructor::hasInstanceInAnyWorld(v8::Handle<v8::Value> jsValue , v8::Isolate* isolate) 163 bool V8TestInterfaceNamedConstructor::hasInstanceInAnyWorld(v8::Handle<v8::Value > jsValue, v8::Isolate* isolate)
176 { 164 {
177 return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e, MainWorld) 165 return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e, MainWorld)
178 || V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e, IsolatedWorld) 166 || V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e, IsolatedWorld)
179 || V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e, WorkerWorld); 167 || V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValu e, WorkerWorld);
180 } 168 }
181 169
182 ActiveDOMObject* V8TestNamedConstructor::toActiveDOMObject(v8::Handle<v8::Object > wrapper) 170 v8::Handle<v8::Object> V8TestInterfaceNamedConstructor::createWrapper(PassRefPtr <TestInterfaceNamedConstructor> impl, v8::Handle<v8::Object> creationContext, v8 ::Isolate* isolate)
183 {
184 return toNative(wrapper);
185 }
186
187 v8::Handle<v8::Object> V8TestNamedConstructor::createWrapper(PassRefPtr<TestName dConstructor> impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate )
188 { 171 {
189 ASSERT(impl); 172 ASSERT(impl);
190 ASSERT(!DOMDataStore::containsWrapper<V8TestNamedConstructor>(impl.get(), is olate)); 173 ASSERT(!DOMDataStore::containsWrapper<V8TestInterfaceNamedConstructor>(impl. get(), isolate));
191 if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) { 174 if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) {
192 const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObje ct(impl.get()); 175 const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObje ct(impl.get());
193 // Might be a XXXConstructor::wrapperTypeInfo instead of an XXX::wrapper TypeInfo. These will both have 176 // Might be a XXXConstructor::wrapperTypeInfo instead of an XXX::wrapper TypeInfo. These will both have
194 // the same object de-ref functions, though, so use that as the basis of the check. 177 // the same object de-ref functions, though, so use that as the basis of the check.
195 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == wrapperTypeInfo.derefObjectFunction); 178 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == wrapperTypeInfo.derefObjectFunction);
196 } 179 }
197 180
198 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext , &wrapperTypeInfo, toInternalPointer(impl.get()), isolate); 181 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext , &wrapperTypeInfo, toInternalPointer(impl.get()), isolate);
199 if (UNLIKELY(wrapper.IsEmpty())) 182 if (UNLIKELY(wrapper.IsEmpty()))
200 return wrapper; 183 return wrapper;
201 184
202 installPerContextEnabledProperties(wrapper, impl.get(), isolate); 185 installPerContextEnabledProperties(wrapper, impl.get(), isolate);
203 V8DOMWrapper::associateObjectWithWrapper<V8TestNamedConstructor>(impl, &wrap perTypeInfo, wrapper, isolate, WrapperConfiguration::Dependent); 186 V8DOMWrapper::associateObjectWithWrapper<V8TestInterfaceNamedConstructor>(im pl, &wrapperTypeInfo, wrapper, isolate, WrapperConfiguration::Independent);
204 return wrapper; 187 return wrapper;
205 } 188 }
206 189
207 void V8TestNamedConstructor::derefObject(void* object) 190 void V8TestInterfaceNamedConstructor::derefObject(void* object)
208 { 191 {
209 fromInternalPointer(object)->deref(); 192 fromInternalPointer(object)->deref();
210 } 193 }
211 194
212 template<> 195 template<>
213 v8::Handle<v8::Value> toV8NoInline(TestNamedConstructor* impl, v8::Handle<v8::Ob ject> creationContext, v8::Isolate* isolate) 196 v8::Handle<v8::Value> toV8NoInline(TestInterfaceNamedConstructor* impl, v8::Hand le<v8::Object> creationContext, v8::Isolate* isolate)
214 { 197 {
215 return toV8(impl, creationContext, isolate); 198 return toV8(impl, creationContext, isolate);
216 } 199 }
217 200
218 } // namespace WebCore 201 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698