Chromium Code Reviews| Index: Source/bindings/core/v8/Dictionary.cpp |
| diff --git a/Source/bindings/core/v8/Dictionary.cpp b/Source/bindings/core/v8/Dictionary.cpp |
| index 91b09a48d1f3e5ddc70a0b17a746f658336fead6..1efca2be8f06e9a7371606689a8da4f13fb47e63 100644 |
| --- a/Source/bindings/core/v8/Dictionary.cpp |
| +++ b/Source/bindings/core/v8/Dictionary.cpp |
| @@ -46,6 +46,15 @@ |
| namespace blink { |
| +#define TO_OBJECT_WITH_CHECK(context, value, object) \ |
| +{ \ |
| + v8::MaybeLocal<v8::Object> maybeObject = value->ToObject(m_context); \ |
| + if (maybeObject.IsEmpty()) \ |
| + return false; \ |
| + if (!maybeObject.ToLocal(&object)) \ |
| + return false; \ |
| +} |
| + |
| static ExceptionState& emptyExceptionState() |
| { |
| AtomicallyInitializedStaticReference(WTF::ThreadSpecific<NonThrowableExceptionState>, exceptionState, new ThreadSpecific<NonThrowableExceptionState>); |
| @@ -65,6 +74,7 @@ Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolat |
| { |
| ASSERT(m_isolate); |
| ASSERT(m_exceptionState); |
| + subscribeScriptStateDisposal(); |
| #if ENABLE(ASSERT) |
| m_exceptionState->onStackObjectChecker().add(this); |
| #endif |
| @@ -72,6 +82,7 @@ Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolat |
| Dictionary::~Dictionary() |
| { |
| + unsubscribeScriptStateDisposal(); |
| #if ENABLE(ASSERT) |
| if (m_exceptionState) |
| m_exceptionState->onStackObjectChecker().remove(this); |
| @@ -80,8 +91,10 @@ Dictionary::~Dictionary() |
| Dictionary& Dictionary::operator=(const Dictionary& optionsObject) |
| { |
| + unsubscribeScriptStateDisposal(); |
| m_options = optionsObject.m_options; |
| m_isolate = optionsObject.m_isolate; |
| + subscribeScriptStateDisposal(); |
| #if ENABLE(ASSERT) |
| if (m_exceptionState) |
| m_exceptionState->onStackObjectChecker().remove(this); |
| @@ -115,14 +128,14 @@ bool Dictionary::hasProperty(const String& key) const |
| { |
| if (isUndefinedOrNull()) |
| return false; |
| - v8::Local<v8::Object> options = m_options->ToObject(m_isolate); |
| - ASSERT(!options.IsEmpty()); |
| + v8::Local<v8::Object> object; |
| + TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| ASSERT(m_isolate); |
| ASSERT(m_isolate == v8::Isolate::GetCurrent()); |
| ASSERT(m_exceptionState); |
| v8::Handle<v8::String> v8Key = v8String(m_isolate, key); |
| - if (!options->Has(v8Key)) |
| + if (v8Key.IsEmpty() || !object->Has(v8Key)) |
|
bashi
2015/03/03 04:25:05
This seems redundant, but not sure we can omit IsE
|
| return false; |
| return true; |
| @@ -132,19 +145,17 @@ bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const |
| { |
| if (isUndefinedOrNull()) |
| return false; |
| - v8::Local<v8::Object> options = m_options->ToObject(m_isolate); |
| - ASSERT(!options.IsEmpty()); |
| + v8::Local<v8::Object> object; |
| + TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| ASSERT(m_isolate); |
| ASSERT(m_isolate == v8::Isolate::GetCurrent()); |
| ASSERT(m_exceptionState); |
| v8::Handle<v8::String> v8Key = v8String(m_isolate, key); |
| - if (!options->Has(v8Key)) |
| - return false; |
| - value = options->Get(v8Key); |
| - if (value.IsEmpty()) |
| + if (v8Key.IsEmpty() || !object->Has(v8Key)) |
| return false; |
| - return true; |
| + value = object->Get(v8Key); |
| + return !value.IsEmpty(); |
| } |
| bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const |
| @@ -171,11 +182,11 @@ bool Dictionary::set(const String& key, const v8::Handle<v8::Value>& value) |
| { |
| if (isUndefinedOrNull()) |
| return false; |
| - v8::Local<v8::Object> options = m_options->ToObject(m_isolate); |
| - ASSERT(!options.IsEmpty()); |
| + v8::Local<v8::Object> object; |
| + TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| ASSERT(m_exceptionState); |
| - return options->Set(v8String(m_isolate, key), value); |
| + return object->Set(v8String(m_isolate, key), value); |
| } |
| bool Dictionary::set(const String& key, const String& value) |
| @@ -216,19 +227,24 @@ bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMa |
| if (!isObject()) |
| return false; |
| - v8::Handle<v8::Object> options = m_options->ToObject(m_isolate); |
| - if (options.IsEmpty()) |
| - return false; |
| + v8::Local<v8::Object> object; |
| + TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| - v8::Local<v8::Array> properties = options->GetOwnPropertyNames(); |
| + v8::Local<v8::Array> properties = object->GetOwnPropertyNames(); |
| if (properties.IsEmpty()) |
| return true; |
| for (uint32_t i = 0; i < properties->Length(); ++i) { |
| - v8::Local<v8::String> key = properties->Get(i)->ToString(m_isolate); |
| - if (!options->Has(key)) |
| + v8::Local<v8::Value> property = properties->Get(i); |
| + if (property.IsEmpty()) |
| + continue; |
| + v8::MaybeLocal<v8::String> maybeKey = properties->Get(i)->ToString(m_context); |
| + v8::Local<v8::String> key; |
| + if (!maybeKey.ToLocal(&key) || !object->Has(key)) |
| continue; |
| - v8::Local<v8::Value> value = options->Get(key); |
| + v8::Local<v8::Value> value = object->Get(key); |
| + if (value.IsEmpty()) |
| + continue; |
| TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); |
| TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false); |
| if (!static_cast<const String&>(stringKey).isEmpty()) |
| @@ -243,16 +259,19 @@ bool Dictionary::getPropertyNames(Vector<String>& names) const |
| if (!isObject()) |
| return false; |
| - v8::Handle<v8::Object> options = m_options->ToObject(m_isolate); |
| - if (options.IsEmpty()) |
| - return false; |
| + v8::Local<v8::Object> object; |
| + TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| - v8::Local<v8::Array> properties = options->GetPropertyNames(); |
| + v8::Local<v8::Array> properties = object->GetPropertyNames(); |
| if (properties.IsEmpty()) |
| return true; |
| for (uint32_t i = 0; i < properties->Length(); ++i) { |
| - v8::Local<v8::String> key = properties->Get(i)->ToString(m_isolate); |
| - if (!options->Has(key)) |
| + v8::Local<v8::Value> property = properties->Get(i); |
| + if (property.IsEmpty()) |
| + continue; |
| + v8::MaybeLocal<v8::String> maybeKey = properties->Get(i)->ToString(m_context); |
| + v8::Local<v8::String> key; |
| + if (!maybeKey.ToLocal(&key) || !object->Has(key)) |
| continue; |
| TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); |
| names.append(stringKey); |
| @@ -285,4 +304,27 @@ void Dictionary::ConversionContext::throwTypeError(const String& detail) |
| exceptionState().throwTypeError(detail); |
| } |
| +void Dictionary::willDisposeScriptState(ScriptState*) |
| +{ |
| + m_context.Clear(); |
| +} |
| + |
| +void Dictionary::subscribeScriptStateDisposal() |
| +{ |
| + if (m_isolate) { |
| + ScriptState* scriptState = ScriptState::current(m_isolate); |
| + scriptState->addObserver(this); |
| + m_context = scriptState->context(); |
| + ASSERT(!m_context.IsEmpty()); |
| + } |
| +} |
| + |
| +void Dictionary::unsubscribeScriptStateDisposal() |
| +{ |
| + if (m_isolate) { |
| + ScriptState* scriptState = ScriptState::current(m_isolate); |
| + scriptState->removeObserver(this); |
| + } |
| +} |
| + |
| } // namespace blink |