#include "config.h"
#include "core/inspector/ScriptArguments.h"
-#include "bindings/v8/ScriptScope.h"
-#include "bindings/v8/ScriptValue.h"
+#include "bindings/core/v8/ScriptValue.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "wtf/text/StringBuilder.h"
+#include <v8.h>
-namespace WebCore {
+namespace blink {
-PassRefPtr<ScriptArguments> ScriptArguments::create(ScriptState* scriptState, Vector<ScriptValue>& arguments)
+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.appendLiteral("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)
{
- return adoptRef(new ScriptArguments(scriptState, arguments));
+ return adoptRefWillBeNoop(new ScriptArguments(scriptState, arguments));
}
ScriptArguments::ScriptArguments(ScriptState* scriptState, Vector<ScriptValue>& arguments)
m_arguments.swap(arguments);
}
-ScriptArguments::~ScriptArguments()
-{
-}
-
const ScriptValue &ScriptArguments::argumentAt(size_t index) const
{
ASSERT(m_arguments.size() > index);
return m_arguments[index];
}
-ScriptState* ScriptArguments::globalState() const
-{
- return m_scriptState.get();
-}
-
-bool ScriptArguments::getFirstArgumentAsString(String& result, bool checkForNullOrUndefined)
+bool ScriptArguments::getFirstArgumentAsString(String& result) const
{
if (!argumentCount())
return false;
const ScriptValue& value = argumentAt(0);
- ScriptScope scope(m_scriptState.get());
- if (checkForNullOrUndefined && (value.isNull() || value.isUndefined()))
- return false;
-
- if (!globalState()) {
- ASSERT_NOT_REACHED();
- return false;
- }
-
- result = value.toString();
+ ScriptState::Scope scope(m_scriptState.get());
+ result = V8ValueStringBuilder::toString(value.v8Value(), value.isolate());
return true;
}
-} // namespace WebCore
+} // namespace blink