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

Side by Side Diff: content/renderer/v8_value_converter_impl.cc

Issue 10890002: Make V8ValueConverter.FromV8Value behave similarly to JSON.stringify (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: no more function Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/v8_value_converter_impl.h" 5 #include "content/renderer/v8_value_converter_impl.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/values.h" 11 #include "base/values.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h" 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebArrayBuff erView.h" 13 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebArrayBuff erView.h"
14 #include "v8/include/v8.h" 14 #include "v8/include/v8.h"
15 15
16 using base::BinaryValue; 16 using base::BinaryValue;
17 using base::DictionaryValue; 17 using base::DictionaryValue;
18 using base::ListValue; 18 using base::ListValue;
19 using base::StringValue; 19 using base::StringValue;
20 using base::Value; 20 using base::Value;
21 21
22 namespace content { 22 namespace content {
23 23
24 V8ValueConverter* V8ValueConverter::create() { 24 V8ValueConverter* V8ValueConverter::create() {
25 return new V8ValueConverterImpl(); 25 return new V8ValueConverterImpl();
26 } 26 }
27 } // namespace content 27 } // namespace content
28 28
29 V8ValueConverterImpl::V8ValueConverterImpl() 29 V8ValueConverterImpl::V8ValueConverterImpl()
30 : undefined_allowed_(false), 30 : date_allowed_(false),
31 date_allowed_(false), 31 reg_exp_allowed_(false),
32 regexp_allowed_(false), 32 function_allowed_(false),
33 strip_null_from_objects_(false) { 33 strip_null_from_objects_(false) {
34 } 34 }
35 35
36 bool V8ValueConverterImpl::GetUndefinedAllowed() const {
37 return undefined_allowed_;
38 }
39
40 void V8ValueConverterImpl::SetUndefinedAllowed(bool val) {
41 undefined_allowed_ = val;
42 }
43
44 bool V8ValueConverterImpl::GetDateAllowed() const {
45 return date_allowed_;
46 }
47
48 void V8ValueConverterImpl::SetDateAllowed(bool val) { 36 void V8ValueConverterImpl::SetDateAllowed(bool val) {
49 date_allowed_ = val; 37 date_allowed_ = val;
50 } 38 }
51 39
52 bool V8ValueConverterImpl::GetRegexpAllowed() const { 40 void V8ValueConverterImpl::SetRegExpAllowed(bool val) {
53 return regexp_allowed_; 41 reg_exp_allowed_ = val;
54 } 42 }
55 43
56 void V8ValueConverterImpl::SetRegexpAllowed(bool val) { 44 void V8ValueConverterImpl::SetFunctionAllowed(bool val) {
57 regexp_allowed_ = val; 45 function_allowed_ = val;
58 }
59
60 bool V8ValueConverterImpl::GetStripNullFromObjects() const {
61 return strip_null_from_objects_;
62 } 46 }
63 47
64 void V8ValueConverterImpl::SetStripNullFromObjects(bool val) { 48 void V8ValueConverterImpl::SetStripNullFromObjects(bool val) {
65 strip_null_from_objects_ = val; 49 strip_null_from_objects_ = val;
66 } 50 }
67 51
68 v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Value( 52 v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Value(
69 const Value* value, v8::Handle<v8::Context> context) const { 53 const Value* value, v8::Handle<v8::Context> context) const {
70 v8::Context::Scope context_scope(context); 54 v8::Context::Scope context_scope(context);
71 v8::HandleScope handle_scope; 55 v8::HandleScope handle_scope;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 return Value::CreateIntegerValue(val->ToInt32()->Value()); 177 return Value::CreateIntegerValue(val->ToInt32()->Value());
194 178
195 if (val->IsNumber()) 179 if (val->IsNumber())
196 return Value::CreateDoubleValue(val->ToNumber()->Value()); 180 return Value::CreateDoubleValue(val->ToNumber()->Value());
197 181
198 if (val->IsString()) { 182 if (val->IsString()) {
199 v8::String::Utf8Value utf8(val->ToString()); 183 v8::String::Utf8Value utf8(val->ToString());
200 return Value::CreateStringValue(std::string(*utf8, utf8.length())); 184 return Value::CreateStringValue(std::string(*utf8, utf8.length()));
201 } 185 }
202 186
203 if (undefined_allowed_ && val->IsUndefined()) 187 if (val->IsUndefined())
204 return Value::CreateNullValue(); 188 // JSON.stringify ignores undefined.
189 return NULL;
205 190
206 if (date_allowed_ && val->IsDate()) { 191 if (val->IsDate()) {
192 if (!date_allowed_)
193 // JSON.stringify would convert this to a string, but an object is more
194 // consistent within this class.
195 return FromV8Object(val->ToObject(), unique_set);
207 v8::Date* date = v8::Date::Cast(*val); 196 v8::Date* date = v8::Date::Cast(*val);
208 return Value::CreateDoubleValue(date->NumberValue() / 1000.0); 197 return Value::CreateDoubleValue(date->NumberValue() / 1000.0);
209 } 198 }
210 199
211 if (regexp_allowed_ && val->IsRegExp()) { 200 if (val->IsRegExp()) {
212 return Value::CreateStringValue( 201 if (!reg_exp_allowed_)
213 *v8::String::Utf8Value(val->ToString())); 202 // JSON.stringify converts to an object.
203 return FromV8Object(val->ToObject(), unique_set);
204 return Value::CreateStringValue(*v8::String::Utf8Value(val->ToString()));
214 } 205 }
215 206
216 // v8::Value doesn't have a ToArray() method for some reason. 207 // v8::Value doesn't have a ToArray() method for some reason.
217 if (val->IsArray()) 208 if (val->IsArray())
218 return FromV8Array(val.As<v8::Array>(), unique_set); 209 return FromV8Array(val.As<v8::Array>(), unique_set);
219 210
211 if (val->IsFunction()) {
212 if (!function_allowed_)
213 // JSON.stringify refuses to convert function(){}.
214 return NULL;
215 return FromV8Object(val->ToObject(), unique_set);
216 }
217
220 if (val->IsObject()) { 218 if (val->IsObject()) {
221 BinaryValue* binary_value = FromV8Buffer(val); 219 BinaryValue* binary_value = FromV8Buffer(val);
222 if (binary_value) { 220 if (binary_value) {
223 return binary_value; 221 return binary_value;
224 } else { 222 } else {
225 return FromV8Object(val->ToObject(), unique_set); 223 return FromV8Object(val->ToObject(), unique_set);
226 } 224 }
227 } 225 }
226
228 LOG(ERROR) << "Unexpected v8 value type encountered."; 227 LOG(ERROR) << "Unexpected v8 value type encountered.";
229 return Value::CreateNullValue(); 228 return NULL;
230 } 229 }
231 230
232 Value* V8ValueConverterImpl::FromV8Array(v8::Handle<v8::Array> val, 231 Value* V8ValueConverterImpl::FromV8Array(v8::Handle<v8::Array> val,
233 std::set<int>* unique_set) const { 232 std::set<int>* unique_set) const {
234 if (unique_set && unique_set->count(val->GetIdentityHash())) 233 if (unique_set && unique_set->count(val->GetIdentityHash()))
235 return Value::CreateNullValue(); 234 return Value::CreateNullValue();
236 235
237 scoped_ptr<v8::Context::Scope> scope; 236 scoped_ptr<v8::Context::Scope> scope;
238 // If val was created in a different context than our current one, change to 237 // If val was created in a different context than our current one, change to
239 // that context, but change back after val is converted. 238 // that context, but change back after val is converted.
(...skipping 11 matching lines...) Expand all
251 v8::Handle<v8::Value> child_v8 = val->Get(i); 250 v8::Handle<v8::Value> child_v8 = val->Get(i);
252 if (try_catch.HasCaught()) { 251 if (try_catch.HasCaught()) {
253 LOG(ERROR) << "Getter for index " << i << " threw an exception."; 252 LOG(ERROR) << "Getter for index " << i << " threw an exception.";
254 child_v8 = v8::Null(); 253 child_v8 = v8::Null();
255 } 254 }
256 255
257 if (!val->HasRealIndexedProperty(i)) 256 if (!val->HasRealIndexedProperty(i))
258 continue; 257 continue;
259 258
260 Value* child = FromV8ValueImpl(child_v8, unique_set); 259 Value* child = FromV8ValueImpl(child_v8, unique_set);
261 CHECK(child); 260 if (child)
262 261 result->Append(child);
263 result->Append(child); 262 else
263 // JSON.stringify puts null in places where values don't serialize, for
264 // example undefined and functions. Emulate that behavior.
265 result->Append(Value::CreateNullValue());
264 } 266 }
265 return result; 267 return result;
266 } 268 }
267 269
268 base::BinaryValue* V8ValueConverterImpl::FromV8Buffer( 270 base::BinaryValue* V8ValueConverterImpl::FromV8Buffer(
269 v8::Handle<v8::Value> val) const { 271 v8::Handle<v8::Value> val) const {
270 char* data = NULL; 272 char* data = NULL;
271 size_t length = 0; 273 size_t length = 0;
272 274
273 scoped_ptr<WebKit::WebArrayBuffer> array_buffer( 275 scoped_ptr<WebKit::WebArrayBuffer> array_buffer(
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 v8::TryCatch try_catch; 330 v8::TryCatch try_catch;
329 v8::Handle<v8::Value> child_v8 = val->Get(key); 331 v8::Handle<v8::Value> child_v8 = val->Get(key);
330 332
331 if (try_catch.HasCaught()) { 333 if (try_catch.HasCaught()) {
332 LOG(ERROR) << "Getter for property " << *name_utf8 334 LOG(ERROR) << "Getter for property " << *name_utf8
333 << " threw an exception."; 335 << " threw an exception.";
334 child_v8 = v8::Null(); 336 child_v8 = v8::Null();
335 } 337 }
336 338
337 scoped_ptr<Value> child(FromV8ValueImpl(child_v8, unique_set)); 339 scoped_ptr<Value> child(FromV8ValueImpl(child_v8, unique_set));
338 CHECK(child.get()); 340 if (!child.get())
341 // JSON.stringify skips properties whose values don't serialize, for
342 // example undefined and functions. Emulate that behavior.
343 continue;
339 344
340 // Strip null if asked (and since undefined is turned into null, undefined 345 // Strip null if asked (and since undefined is turned into null, undefined
341 // too). The use case for supporting this is JSON-schema support, 346 // too). The use case for supporting this is JSON-schema support,
342 // specifically for extensions, where "optional" JSON properties may be 347 // specifically for extensions, where "optional" JSON properties may be
343 // represented as null, yet due to buggy legacy code elsewhere isn't 348 // represented as null, yet due to buggy legacy code elsewhere isn't
344 // treated as such (potentially causing crashes). For example, the 349 // treated as such (potentially causing crashes). For example, the
345 // "tabs.create" function takes an object as its first argument with an 350 // "tabs.create" function takes an object as its first argument with an
346 // optional "windowId" property. 351 // optional "windowId" property.
347 // 352 //
348 // Given just 353 // Given just
(...skipping 10 matching lines...) Expand all
359 // We can avoid all bugs related to this by stripping null. 364 // We can avoid all bugs related to this by stripping null.
360 if (strip_null_from_objects_ && child->IsType(Value::TYPE_NULL)) 365 if (strip_null_from_objects_ && child->IsType(Value::TYPE_NULL))
361 continue; 366 continue;
362 367
363 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()), 368 result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()),
364 child.release()); 369 child.release());
365 } 370 }
366 371
367 return result.release(); 372 return result.release();
368 } 373 }
OLDNEW
« no previous file with comments | « content/renderer/v8_value_converter_impl.h ('k') | content/renderer/v8_value_converter_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698