blob: e2548fc7d2688f87336d30a46da0522aa331aab5 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "bindings/core/v8/DictionaryIterator.h"
#include "bindings/core/v8/Dictionary.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8StringResource.h"
#include "wtf/text/WTFString.h"
namespace blink {
DictionaryIterator::DictionaryIterator(v8::Local<v8::Object> iterator,
v8::Isolate* isolate)
: m_isolate(isolate),
m_iterator(iterator),
m_nextKey(v8String(isolate, "next")),
m_doneKey(v8String(isolate, "done")),
m_valueKey(v8String(isolate, "value")),
m_done(false) {
DCHECK(!iterator.IsEmpty());
}
bool DictionaryIterator::next(ExecutionContext* executionContext,
ExceptionState& exceptionState) {
DCHECK(!isNull());
v8::TryCatch tryCatch(m_isolate);
v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
v8::Local<v8::Value> next;
if (!m_iterator->Get(context, m_nextKey).ToLocal(&next)) {
CHECK(!tryCatch.Exception().IsEmpty());
exceptionState.rethrowV8Exception(tryCatch.Exception());
m_done = true;
return false;
}
if (!next->IsFunction()) {
exceptionState.throwTypeError("Expected next() function on iterator.");
m_done = true;
return false;
}
v8::Local<v8::Value> result;
if (!V8ScriptRunner::callFunction(v8::Local<v8::Function>::Cast(next),
executionContext, m_iterator, 0, nullptr,
m_isolate)
.ToLocal(&result)) {
CHECK(!tryCatch.Exception().IsEmpty());
exceptionState.rethrowV8Exception(tryCatch.Exception());
m_done = true;
return false;
}
if (!result->IsObject()) {
exceptionState.throwTypeError(
"Expected iterator.next() to return an Object.");
m_done = true;
return false;
}
v8::Local<v8::Object> resultObject = v8::Local<v8::Object>::Cast(result);
m_value = resultObject->Get(context, m_valueKey);
if (m_value.IsEmpty()) {
CHECK(!tryCatch.Exception().IsEmpty());
exceptionState.rethrowV8Exception(tryCatch.Exception());
}
v8::Local<v8::Value> done;
v8::Local<v8::Boolean> doneBoolean;
if (!resultObject->Get(context, m_doneKey).ToLocal(&done) ||
!done->ToBoolean(context).ToLocal(&doneBoolean)) {
CHECK(!tryCatch.Exception().IsEmpty());
exceptionState.rethrowV8Exception(tryCatch.Exception());
m_done = true;
return false;
}
m_done = doneBoolean->Value();
return !m_done;
}
bool DictionaryIterator::valueAsDictionary(Dictionary& result,
ExceptionState& exceptionState) {
DCHECK(!isNull());
DCHECK(!m_done);
v8::Local<v8::Value> value;
if (!v8Call(m_value, value) || !value->IsObject())
return false;
result = Dictionary(m_isolate, value, exceptionState);
return true;
}
bool DictionaryIterator::valueAsString(String& result) {
DCHECK(!isNull());
DCHECK(!m_done);
v8::Local<v8::Value> value;
if (!v8Call(m_value, value))
return false;
V8StringResource<> stringValue(value);
if (!stringValue.prepare())
return false;
result = stringValue;
return true;
}
} // namespace blink