| 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;
|
| }
|
|
|
|
|