Chromium Code Reviews| Index: Source/core/inspector/ScriptArguments.cpp |
| diff --git a/Source/core/inspector/ScriptArguments.cpp b/Source/core/inspector/ScriptArguments.cpp |
| index bbb163955a990dd38748ab91cda43b70f7445ae1..76349f1529fb7f5a3ee94a52497d7992c9f4d071 100644 |
| --- a/Source/core/inspector/ScriptArguments.cpp |
| +++ b/Source/core/inspector/ScriptArguments.cpp |
| @@ -33,10 +33,127 @@ |
| #include "bindings/core/v8/ScriptValue.h" |
| #include "bindings/core/v8/V8Binding.h" |
| +#include "wtf/Vector.h" |
| +#include "wtf/text/StringBuilder.h" |
| #include <v8.h> |
| namespace WebCore { |
| +namespace { |
| + |
| +static const int maxArrayItemsLimit = 10000; |
| +static const int maxStackDepthLimit = 32; |
| + |
| +class V8ValueStringBuilder { |
| +public: |
| + static String toString(v8::Handle<v8::Value> value) |
| + { |
| + V8ValueStringBuilder builder; |
| + if (!builder.append(value)) |
|
yurys
2014/07/14 16:36:09
This check seems redundant.
aandrey
2014/07/18 08:54:47
Nope, builder can also fail w/o throwing an except
|
| + return String(); |
| + return builder.toString(); |
| + } |
| + |
| +private: |
| + enum { |
| + IgnoreNull = 1 << 0, |
| + IgnoreUndefined = 1 << 1, |
| + }; |
| + |
| + V8ValueStringBuilder() : m_arrayLimit(maxArrayItemsLimit) { } |
| + |
| + bool append(v8::Handle<v8::Value> value, unsigned ignoreOptions = 0) |
| + { |
| + if (value.IsEmpty()) |
| + return true; |
| + if ((ignoreOptions & IgnoreNull) && value->IsNull()) |
| + return true; |
| + if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined()) |
| + return true; |
| + if (value->IsString()) |
| + return append(v8::Handle<v8::String>::Cast(value)); |
| + if (value->IsStringObject()) |
| + return append(v8::Handle<v8::StringObject>::Cast(value)->ValueOf()); |
| + if (value->IsSymbol()) |
| + return append(v8::Handle<v8::Symbol>::Cast(value)); |
| + if (value->IsSymbolObject()) |
| + return append(v8::Handle<v8::SymbolObject>::Cast(value)->ValueOf()); |
| + if (value->IsNumberObject()) { |
| + m_builder.appendNumber(v8::Handle<v8::NumberObject>::Cast(value)->ValueOf()); |
| + return true; |
| + } |
| + if (value->IsBooleanObject()) { |
| + m_builder.append(v8::Handle<v8::BooleanObject>::Cast(value)->ValueOf() ? "true" : "false"); |
| + return true; |
| + } |
| + if (value->IsArray()) |
| + return append(v8::Handle<v8::Array>::Cast(value)); |
| + if (value->IsObject() |
| + && !value->IsDate() |
| + && !value->IsFunction() |
| + && !value->IsNativeError() |
| + && !value->IsRegExp()) |
| + return append(v8::Handle<v8::Object>::Cast(value)->ObjectProtoToString()); |
| + return append(value->ToString()); |
| + } |
| + |
| + bool append(v8::Handle<v8::Array> array) |
| + { |
| + if (m_visitedArrays.contains(array)) |
| + return true; |
| + uint32_t length = array->Length(); |
| + if (length > m_arrayLimit) |
| + return false; |
| + if (m_visitedArrays.size() > maxStackDepthLimit) |
| + return false; |
| + |
| + bool result = true; |
| + m_arrayLimit -= length; |
| + m_visitedArrays.append(array); |
| + for (uint32_t i = 0; i < length; ++i) { |
| + if (i) |
| + m_builder.append(','); |
| + if (!append(array->Get(i), IgnoreNull | IgnoreUndefined)) { |
| + result = false; |
| + break; |
| + } |
| + } |
| + m_visitedArrays.removeLast(); |
| + return result; |
| + } |
| + |
| + bool append(v8::Handle<v8::Symbol> symbol) |
| + { |
| + m_builder.append("Symbol("); |
| + bool result = append(symbol->Name(), IgnoreUndefined); |
| + m_builder.append(')'); |
| + return result; |
| + } |
| + |
| + bool append(v8::Handle<v8::String> string) |
| + { |
| + if (m_tryCatch.HasCaught()) |
| + return false; |
| + if (!string.IsEmpty()) |
| + m_builder.append(toCoreString(string)); |
| + return true; |
| + } |
| + |
| + String toString() |
| + { |
| + if (m_tryCatch.HasCaught()) |
| + return String(); |
| + return m_builder.toString(); |
| + } |
| + |
| + uint32_t m_arrayLimit; |
| + StringBuilder m_builder; |
| + Vector<v8::Handle<v8::Array> > m_visitedArrays; |
| + v8::TryCatch m_tryCatch; |
| +}; |
| + |
| +} // namespace |
| + |
| DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ScriptArguments) |
| PassRefPtrWillBeRawPtr<ScriptArguments> ScriptArguments::create(ScriptState* scriptState, Vector<ScriptValue>& arguments) |
| @@ -66,10 +183,7 @@ bool ScriptArguments::getFirstArgumentAsString(String& result, bool checkForNull |
| if (checkForNullOrUndefined && (value.isNull() || value.isUndefined())) |
| return false; |
| - // We intentionally ignore an exception that can be thrown in ToString(). |
| - v8::TryCatch block; |
| - v8::Handle<v8::String> string = value.v8Value()->ToString(); |
| - result = string.IsEmpty() ? String() : toCoreString(string); |
| + result = V8ValueStringBuilder::toString(value.v8Value()); |
| return true; |
| } |