blob: 3f725f36690d7ff814ab032d9b7f9ab7f05097e9 [file] [log] [blame]
// Copyright 2014 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 "third_party/blink/renderer/core/testing/dictionary_test.h"
#include "third_party/blink/renderer/bindings/core/v8/script_iterator.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/testing/internal_dictionary.h"
#include "third_party/blink/renderer/core/testing/internal_dictionary_derived.h"
#include "third_party/blink/renderer/core/testing/internal_dictionary_derived_derived.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
namespace {
ScriptIterator GetIterator(const Dictionary& iterable,
ExecutionContext* execution_context) {
v8::Local<v8::Value> iterator_getter;
v8::Isolate* isolate = iterable.GetIsolate();
if (!iterable.Get(v8::Symbol::GetIterator(isolate), iterator_getter) ||
!iterator_getter->IsFunction()) {
return nullptr;
}
v8::Local<v8::Value> iterator;
if (!V8ScriptRunner::CallFunction(
v8::Local<v8::Function>::Cast(iterator_getter), execution_context,
iterable.V8Value(), 0, nullptr, isolate)
.ToLocal(&iterator))
return nullptr;
if (!iterator->IsObject())
return nullptr;
return ScriptIterator(v8::Local<v8::Object>::Cast(iterator), isolate);
}
} // namespace
DictionaryTest::DictionaryTest() : required_boolean_member_(false) {}
DictionaryTest::~DictionaryTest() = default;
void DictionaryTest::set(const InternalDictionary* testing_dictionary) {
Reset();
if (testing_dictionary->hasLongMember())
long_member_ = testing_dictionary->longMember();
if (testing_dictionary->hasLongMemberWithClamp())
long_member_with_clamp_ = testing_dictionary->longMemberWithClamp();
if (testing_dictionary->hasLongMemberWithEnforceRange()) {
long_member_with_enforce_range_ =
testing_dictionary->longMemberWithEnforceRange();
}
long_member_with_default_ = testing_dictionary->longMemberWithDefault();
if (testing_dictionary->hasLongOrNullMember())
long_or_null_member_ = testing_dictionary->longOrNullMember();
// |longOrNullMemberWithDefault| has a default value but can be null, so
// we need to check availability.
if (testing_dictionary->hasLongOrNullMemberWithDefault()) {
long_or_null_member_with_default_ =
testing_dictionary->longOrNullMemberWithDefault();
}
if (testing_dictionary->hasBooleanMember())
boolean_member_ = testing_dictionary->booleanMember();
if (testing_dictionary->hasDoubleMember())
double_member_ = testing_dictionary->doubleMember();
if (testing_dictionary->hasUnrestrictedDoubleMember()) {
unrestricted_double_member_ =
testing_dictionary->unrestrictedDoubleMember();
}
string_member_ = testing_dictionary->stringMember();
string_member_with_default_ = testing_dictionary->stringMemberWithDefault();
byte_string_member_ = testing_dictionary->byteStringMember();
usv_string_member_ = testing_dictionary->usvStringMember();
if (testing_dictionary->hasStringSequenceMember())
string_sequence_member_ = testing_dictionary->stringSequenceMember();
string_sequence_member_with_default_ =
testing_dictionary->stringSequenceMemberWithDefault();
if (testing_dictionary->hasStringSequenceOrNullMember()) {
string_sequence_or_null_member_ =
testing_dictionary->stringSequenceOrNullMember();
}
enum_member_ = testing_dictionary->enumMember();
enum_member_with_default_ = testing_dictionary->enumMemberWithDefault();
enum_or_null_member_ = testing_dictionary->enumOrNullMember();
if (testing_dictionary->hasElementMember())
element_member_ = testing_dictionary->elementMember();
if (testing_dictionary->hasElementOrNullMember())
element_or_null_member_ = testing_dictionary->elementOrNullMember();
object_member_ = testing_dictionary->objectMember();
object_or_null_member_with_default_ =
testing_dictionary->objectOrNullMemberWithDefault();
if (testing_dictionary->hasDoubleOrStringMember())
double_or_string_member_ = testing_dictionary->doubleOrStringMember();
if (testing_dictionary->hasDoubleOrStringSequenceMember()) {
double_or_string_sequence_member_ =
testing_dictionary->doubleOrStringSequenceMember();
}
event_target_or_null_member_ = testing_dictionary->eventTargetOrNullMember();
if (testing_dictionary->hasDictionaryMember()) {
NonThrowableExceptionState exception_state;
dictionary_member_properties_ =
testing_dictionary->dictionaryMember().GetOwnPropertiesAsStringHashMap(
exception_state);
}
if (testing_dictionary->hasInternalEnumOrInternalEnumSequenceMember()) {
internal_enum_or_internal_enum_sequence_ =
testing_dictionary->internalEnumOrInternalEnumSequenceMember();
}
any_member_ = testing_dictionary->anyMember();
callback_function_member_ = testing_dictionary->callbackFunctionMember();
}
InternalDictionary* DictionaryTest::get() {
InternalDictionary* result = InternalDictionary::Create();
GetInternals(result);
return result;
}
ScriptValue DictionaryTest::getDictionaryMemberProperties(
ScriptState* script_state) {
if (!dictionary_member_properties_)
return ScriptValue();
V8ObjectBuilder builder(script_state);
HashMap<String, String> properties = dictionary_member_properties_.value();
for (HashMap<String, String>::iterator it = properties.begin();
it != properties.end(); ++it)
builder.AddString(it->key, it->value);
return builder.GetScriptValue();
}
void DictionaryTest::setDerived(const InternalDictionaryDerived* derived) {
DCHECK(derived->hasRequiredBooleanMember());
set(derived);
if (derived->hasDerivedStringMember())
derived_string_member_ = derived->derivedStringMember();
derived_string_member_with_default_ =
derived->derivedStringMemberWithDefault();
required_boolean_member_ = derived->requiredBooleanMember();
}
InternalDictionaryDerived* DictionaryTest::getDerived() {
InternalDictionaryDerived* result = InternalDictionaryDerived::Create();
GetDerivedInternals(result);
return result;
}
void DictionaryTest::setDerivedDerived(
const InternalDictionaryDerivedDerived* derived) {
setDerived(derived);
if (derived->hasDerivedDerivedStringMember())
derived_derived_string_member_ = derived->derivedDerivedStringMember();
}
InternalDictionaryDerivedDerived* DictionaryTest::getDerivedDerived() {
InternalDictionaryDerivedDerived* result =
InternalDictionaryDerivedDerived::Create();
GetDerivedDerivedInternals(result);
return result;
}
String DictionaryTest::stringFromIterable(
ScriptState* script_state,
Dictionary iterable,
ExceptionState& exception_state) const {
StringBuilder result;
ExecutionContext* execution_context = ExecutionContext::From(script_state);
ScriptIterator iterator = GetIterator(iterable, execution_context);
if (iterator.IsNull())
return g_empty_string;
bool first_loop = true;
while (iterator.Next(execution_context, exception_state)) {
if (exception_state.HadException())
return g_empty_string;
if (first_loop)
first_loop = false;
else
result.Append(',');
v8::Local<v8::Value> value;
if (iterator.GetValue().ToLocal(&value))
result.Append(ToCoreString(value->ToString(script_state->GetIsolate())));
}
return result.ToString();
}
void DictionaryTest::Reset() {
long_member_ = base::nullopt;
long_member_with_clamp_ = base::nullopt;
long_member_with_enforce_range_ = base::nullopt;
long_member_with_default_ = -1; // This value should not be returned.
long_or_null_member_ = base::nullopt;
long_or_null_member_with_default_ = base::nullopt;
boolean_member_ = base::nullopt;
double_member_ = base::nullopt;
unrestricted_double_member_ = base::nullopt;
string_member_ = String();
string_member_with_default_ = String("Should not be returned");
string_sequence_member_ = base::nullopt;
string_sequence_member_with_default_.Fill("Should not be returned", 1);
string_sequence_or_null_member_ = base::nullopt;
enum_member_ = String();
enum_member_with_default_ = String();
enum_or_null_member_ = String();
element_member_ = nullptr;
element_or_null_member_.reset();
object_member_ = ScriptValue();
object_or_null_member_with_default_ = ScriptValue();
double_or_string_member_ = DoubleOrString();
event_target_or_null_member_ = nullptr;
derived_string_member_ = String();
derived_string_member_with_default_ = String();
required_boolean_member_ = false;
dictionary_member_properties_ = base::nullopt;
internal_enum_or_internal_enum_sequence_ =
InternalEnumOrInternalEnumSequence();
any_member_ = ScriptValue();
callback_function_member_ = nullptr;
}
void DictionaryTest::GetInternals(InternalDictionary* dict) {
DCHECK(dict);
if (long_member_)
dict->setLongMember(long_member_.value());
if (long_member_with_clamp_)
dict->setLongMemberWithClamp(long_member_with_clamp_.value());
if (long_member_with_enforce_range_) {
dict->setLongMemberWithEnforceRange(
long_member_with_enforce_range_.value());
}
dict->setLongMemberWithDefault(long_member_with_default_);
if (long_or_null_member_)
dict->setLongOrNullMember(long_or_null_member_.value());
if (long_or_null_member_with_default_) {
dict->setLongOrNullMemberWithDefault(
long_or_null_member_with_default_.value());
}
if (boolean_member_)
dict->setBooleanMember(boolean_member_.value());
if (double_member_)
dict->setDoubleMember(double_member_.value());
if (unrestricted_double_member_)
dict->setUnrestrictedDoubleMember(unrestricted_double_member_.value());
dict->setStringMember(string_member_);
dict->setStringMemberWithDefault(string_member_with_default_);
dict->setByteStringMember(byte_string_member_);
dict->setUsvStringMember(usv_string_member_);
if (string_sequence_member_)
dict->setStringSequenceMember(string_sequence_member_.value());
dict->setStringSequenceMemberWithDefault(
string_sequence_member_with_default_);
if (string_sequence_or_null_member_) {
dict->setStringSequenceOrNullMember(
string_sequence_or_null_member_.value());
}
dict->setEnumMember(enum_member_);
dict->setEnumMemberWithDefault(enum_member_with_default_);
dict->setEnumOrNullMember(enum_or_null_member_);
if (element_member_)
dict->setElementMember(element_member_);
if (element_or_null_member_.has_value())
dict->setElementOrNullMember(element_or_null_member_.value());
dict->setObjectMember(object_member_);
dict->setObjectOrNullMemberWithDefault(object_or_null_member_with_default_);
if (!double_or_string_member_.IsNull())
dict->setDoubleOrStringMember(double_or_string_member_);
if (double_or_string_sequence_member_) {
dict->setDoubleOrStringSequenceMember(
double_or_string_sequence_member_.value());
}
dict->setEventTargetOrNullMember(event_target_or_null_member_);
dict->setInternalEnumOrInternalEnumSequenceMember(
internal_enum_or_internal_enum_sequence_);
dict->setAnyMember(any_member_);
dict->setCallbackFunctionMember(callback_function_member_);
}
void DictionaryTest::GetDerivedInternals(InternalDictionaryDerived* dict) {
GetInternals(dict);
dict->setDerivedStringMember(derived_string_member_);
dict->setDerivedStringMemberWithDefault(derived_string_member_with_default_);
dict->setRequiredBooleanMember(required_boolean_member_);
}
void DictionaryTest::GetDerivedDerivedInternals(
InternalDictionaryDerivedDerived* dict) {
GetDerivedInternals(dict);
dict->setDerivedDerivedStringMember(derived_derived_string_member_);
}
void DictionaryTest::Trace(blink::Visitor* visitor) {
visitor->Trace(element_member_);
visitor->Trace(element_or_null_member_);
visitor->Trace(double_or_string_sequence_member_);
visitor->Trace(event_target_or_null_member_);
visitor->Trace(callback_function_member_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink