Index: Source/core/inspector/ScriptArguments.cpp |
diff --git a/Source/core/inspector/ScriptArguments.cpp b/Source/core/inspector/ScriptArguments.cpp |
index bbb163955a990dd38748ab91cda43b70f7445ae1..c8dc42a2b7e9c2d407392687d7bab2202995cf20 100644 |
--- a/Source/core/inspector/ScriptArguments.cpp |
+++ b/Source/core/inspector/ScriptArguments.cpp |
@@ -33,10 +33,136 @@ |
#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 unsigned maxArrayItemsLimit = 10000; |
+static const unsigned maxStackDepthLimit = 32; |
+ |
+class V8ValueStringBuilder { |
+public: |
+ static String toString(v8::Handle<v8::Value> value, v8::Isolate* isolate) |
+ { |
+ V8ValueStringBuilder builder(isolate); |
+ if (!builder.append(value)) |
+ return String(); |
+ return builder.toString(); |
+ } |
+ |
+private: |
+ enum { |
+ IgnoreNull = 1 << 0, |
+ IgnoreUndefined = 1 << 1, |
+ }; |
+ |
+ V8ValueStringBuilder(v8::Isolate* isolate) |
+ : m_arrayLimit(maxArrayItemsLimit) |
+ , m_isolate(isolate) |
+ { |
+ } |
+ |
+ 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 (toDOMWindow(value, m_isolate)) { |
+ m_builder.append("[object Window]"); |
+ return true; |
+ } |
+ 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; |
+ v8::Isolate* m_isolate; |
+ 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 +192,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(), value.isolate()); |
return true; |
} |