Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 #include "bindings/core/v8/V8Path2D.h" | 39 #include "bindings/core/v8/V8Path2D.h" |
| 40 #include "bindings/core/v8/V8Storage.h" | 40 #include "bindings/core/v8/V8Storage.h" |
| 41 #include "bindings/core/v8/V8TextTrack.h" | 41 #include "bindings/core/v8/V8TextTrack.h" |
| 42 #include "bindings/core/v8/V8VoidCallback.h" | 42 #include "bindings/core/v8/V8VoidCallback.h" |
| 43 #include "bindings/core/v8/V8Window.h" | 43 #include "bindings/core/v8/V8Window.h" |
| 44 #include "core/html/track/TrackBase.h" | 44 #include "core/html/track/TrackBase.h" |
| 45 #include "wtf/MathExtras.h" | 45 #include "wtf/MathExtras.h" |
| 46 | 46 |
| 47 namespace blink { | 47 namespace blink { |
| 48 | 48 |
| 49 #define TO_OBJECT_WITH_CHECK(context, value, object) \ | |
| 50 { \ | |
| 51 v8::MaybeLocal<v8::Object> maybeObject = value->ToObject(m_context); \ | |
| 52 if (maybeObject.IsEmpty()) \ | |
| 53 return false; \ | |
| 54 if (!maybeObject.ToLocal(&object)) \ | |
| 55 return false; \ | |
| 56 } | |
| 57 | |
| 49 static ExceptionState& emptyExceptionState() | 58 static ExceptionState& emptyExceptionState() |
| 50 { | 59 { |
| 51 AtomicallyInitializedStaticReference(WTF::ThreadSpecific<NonThrowableExcepti onState>, exceptionState, new ThreadSpecific<NonThrowableExceptionState>); | 60 AtomicallyInitializedStaticReference(WTF::ThreadSpecific<NonThrowableExcepti onState>, exceptionState, new ThreadSpecific<NonThrowableExceptionState>); |
| 52 return *exceptionState; | 61 return *exceptionState; |
| 53 } | 62 } |
| 54 | 63 |
| 55 Dictionary::Dictionary() | 64 Dictionary::Dictionary() |
| 56 : m_isolate(0) | 65 : m_isolate(0) |
| 57 , m_exceptionState(&emptyExceptionState()) | 66 , m_exceptionState(&emptyExceptionState()) |
| 58 { | 67 { |
| 59 } | 68 } |
| 60 | 69 |
| 61 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolat e, ExceptionState& exceptionState) | 70 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolat e, ExceptionState& exceptionState) |
| 62 : m_options(options) | 71 : m_options(options) |
| 63 , m_isolate(isolate) | 72 , m_isolate(isolate) |
| 64 , m_exceptionState(&exceptionState) | 73 , m_exceptionState(&exceptionState) |
| 65 { | 74 { |
| 66 ASSERT(m_isolate); | 75 ASSERT(m_isolate); |
| 67 ASSERT(m_exceptionState); | 76 ASSERT(m_exceptionState); |
| 77 subscribeScriptStateDisposal(); | |
| 68 #if ENABLE(ASSERT) | 78 #if ENABLE(ASSERT) |
| 69 m_exceptionState->onStackObjectChecker().add(this); | 79 m_exceptionState->onStackObjectChecker().add(this); |
| 70 #endif | 80 #endif |
| 71 } | 81 } |
| 72 | 82 |
| 73 Dictionary::~Dictionary() | 83 Dictionary::~Dictionary() |
| 74 { | 84 { |
| 85 unsubscribeScriptStateDisposal(); | |
| 75 #if ENABLE(ASSERT) | 86 #if ENABLE(ASSERT) |
| 76 if (m_exceptionState) | 87 if (m_exceptionState) |
| 77 m_exceptionState->onStackObjectChecker().remove(this); | 88 m_exceptionState->onStackObjectChecker().remove(this); |
| 78 #endif | 89 #endif |
| 79 } | 90 } |
| 80 | 91 |
| 81 Dictionary& Dictionary::operator=(const Dictionary& optionsObject) | 92 Dictionary& Dictionary::operator=(const Dictionary& optionsObject) |
| 82 { | 93 { |
| 94 unsubscribeScriptStateDisposal(); | |
| 83 m_options = optionsObject.m_options; | 95 m_options = optionsObject.m_options; |
| 84 m_isolate = optionsObject.m_isolate; | 96 m_isolate = optionsObject.m_isolate; |
| 97 subscribeScriptStateDisposal(); | |
| 85 #if ENABLE(ASSERT) | 98 #if ENABLE(ASSERT) |
| 86 if (m_exceptionState) | 99 if (m_exceptionState) |
| 87 m_exceptionState->onStackObjectChecker().remove(this); | 100 m_exceptionState->onStackObjectChecker().remove(this); |
| 88 #endif | 101 #endif |
| 89 m_exceptionState = optionsObject.m_exceptionState; | 102 m_exceptionState = optionsObject.m_exceptionState; |
| 90 #if ENABLE(ASSERT) | 103 #if ENABLE(ASSERT) |
| 91 if (m_exceptionState) | 104 if (m_exceptionState) |
| 92 m_exceptionState->onStackObjectChecker().add(this); | 105 m_exceptionState->onStackObjectChecker().add(this); |
| 93 #endif | 106 #endif |
| 94 return *this; | 107 return *this; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 108 { | 121 { |
| 109 if (m_options.IsEmpty()) | 122 if (m_options.IsEmpty()) |
| 110 return true; | 123 return true; |
| 111 return blink::isUndefinedOrNull(m_options); | 124 return blink::isUndefinedOrNull(m_options); |
| 112 } | 125 } |
| 113 | 126 |
| 114 bool Dictionary::hasProperty(const String& key) const | 127 bool Dictionary::hasProperty(const String& key) const |
| 115 { | 128 { |
| 116 if (isUndefinedOrNull()) | 129 if (isUndefinedOrNull()) |
| 117 return false; | 130 return false; |
| 118 v8::Local<v8::Object> options = m_options->ToObject(m_isolate); | 131 v8::Local<v8::Object> object; |
| 119 ASSERT(!options.IsEmpty()); | 132 TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| 120 | 133 |
| 121 ASSERT(m_isolate); | 134 ASSERT(m_isolate); |
| 122 ASSERT(m_isolate == v8::Isolate::GetCurrent()); | 135 ASSERT(m_isolate == v8::Isolate::GetCurrent()); |
| 123 ASSERT(m_exceptionState); | 136 ASSERT(m_exceptionState); |
| 124 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); | 137 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); |
| 125 if (!options->Has(v8Key)) | 138 if (v8Key.IsEmpty() || !object->Has(v8Key)) |
|
bashi
2015/03/03 04:25:05
This seems redundant, but not sure we can omit IsE
| |
| 126 return false; | 139 return false; |
| 127 | 140 |
| 128 return true; | 141 return true; |
| 129 } | 142 } |
| 130 | 143 |
| 131 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const | 144 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const |
| 132 { | 145 { |
| 133 if (isUndefinedOrNull()) | 146 if (isUndefinedOrNull()) |
| 134 return false; | 147 return false; |
| 135 v8::Local<v8::Object> options = m_options->ToObject(m_isolate); | 148 v8::Local<v8::Object> object; |
| 136 ASSERT(!options.IsEmpty()); | 149 TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| 137 | 150 |
| 138 ASSERT(m_isolate); | 151 ASSERT(m_isolate); |
| 139 ASSERT(m_isolate == v8::Isolate::GetCurrent()); | 152 ASSERT(m_isolate == v8::Isolate::GetCurrent()); |
| 140 ASSERT(m_exceptionState); | 153 ASSERT(m_exceptionState); |
| 141 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); | 154 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); |
| 142 if (!options->Has(v8Key)) | 155 if (v8Key.IsEmpty() || !object->Has(v8Key)) |
| 143 return false; | 156 return false; |
| 144 value = options->Get(v8Key); | 157 value = object->Get(v8Key); |
| 145 if (value.IsEmpty()) | 158 return !value.IsEmpty(); |
| 146 return false; | |
| 147 return true; | |
| 148 } | 159 } |
| 149 | 160 |
| 150 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const | 161 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const |
| 151 { | 162 { |
| 152 return getKey(key, value); | 163 return getKey(key, value); |
| 153 } | 164 } |
| 154 | 165 |
| 155 bool Dictionary::get(const String& key, Dictionary& value) const | 166 bool Dictionary::get(const String& key, Dictionary& value) const |
| 156 { | 167 { |
| 157 v8::Local<v8::Value> v8Value; | 168 v8::Local<v8::Value> v8Value; |
| 158 if (!getKey(key, v8Value)) | 169 if (!getKey(key, v8Value)) |
| 159 return false; | 170 return false; |
| 160 | 171 |
| 161 if (v8Value->IsObject()) { | 172 if (v8Value->IsObject()) { |
| 162 ASSERT(m_isolate); | 173 ASSERT(m_isolate); |
| 163 ASSERT(m_isolate == v8::Isolate::GetCurrent()); | 174 ASSERT(m_isolate == v8::Isolate::GetCurrent()); |
| 164 value = Dictionary(v8Value, m_isolate, *m_exceptionState); | 175 value = Dictionary(v8Value, m_isolate, *m_exceptionState); |
| 165 } | 176 } |
| 166 | 177 |
| 167 return true; | 178 return true; |
| 168 } | 179 } |
| 169 | 180 |
| 170 bool Dictionary::set(const String& key, const v8::Handle<v8::Value>& value) | 181 bool Dictionary::set(const String& key, const v8::Handle<v8::Value>& value) |
| 171 { | 182 { |
| 172 if (isUndefinedOrNull()) | 183 if (isUndefinedOrNull()) |
| 173 return false; | 184 return false; |
| 174 v8::Local<v8::Object> options = m_options->ToObject(m_isolate); | 185 v8::Local<v8::Object> object; |
| 175 ASSERT(!options.IsEmpty()); | 186 TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| 176 ASSERT(m_exceptionState); | 187 ASSERT(m_exceptionState); |
| 177 | 188 |
| 178 return options->Set(v8String(m_isolate, key), value); | 189 return object->Set(v8String(m_isolate, key), value); |
| 179 } | 190 } |
| 180 | 191 |
| 181 bool Dictionary::set(const String& key, const String& value) | 192 bool Dictionary::set(const String& key, const String& value) |
| 182 { | 193 { |
| 183 return set(key, v8String(m_isolate, value)); | 194 return set(key, v8String(m_isolate, value)); |
| 184 } | 195 } |
| 185 | 196 |
| 186 bool Dictionary::set(const String& key, unsigned value) | 197 bool Dictionary::set(const String& key, unsigned value) |
| 187 { | 198 { |
| 188 return set(key, v8::Integer::NewFromUnsigned(m_isolate, value)); | 199 return set(key, v8::Integer::NewFromUnsigned(m_isolate, value)); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 209 | 220 |
| 210 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does n ot have a Dictionary type.")); | 221 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does n ot have a Dictionary type.")); |
| 211 return false; | 222 return false; |
| 212 } | 223 } |
| 213 | 224 |
| 214 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMa p) const | 225 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMa p) const |
| 215 { | 226 { |
| 216 if (!isObject()) | 227 if (!isObject()) |
| 217 return false; | 228 return false; |
| 218 | 229 |
| 219 v8::Handle<v8::Object> options = m_options->ToObject(m_isolate); | 230 v8::Local<v8::Object> object; |
| 220 if (options.IsEmpty()) | 231 TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| 221 return false; | |
| 222 | 232 |
| 223 v8::Local<v8::Array> properties = options->GetOwnPropertyNames(); | 233 v8::Local<v8::Array> properties = object->GetOwnPropertyNames(); |
| 224 if (properties.IsEmpty()) | 234 if (properties.IsEmpty()) |
| 225 return true; | 235 return true; |
| 226 for (uint32_t i = 0; i < properties->Length(); ++i) { | 236 for (uint32_t i = 0; i < properties->Length(); ++i) { |
| 227 v8::Local<v8::String> key = properties->Get(i)->ToString(m_isolate); | 237 v8::Local<v8::Value> property = properties->Get(i); |
| 228 if (!options->Has(key)) | 238 if (property.IsEmpty()) |
| 239 continue; | |
| 240 v8::MaybeLocal<v8::String> maybeKey = properties->Get(i)->ToString(m_con text); | |
| 241 v8::Local<v8::String> key; | |
| 242 if (!maybeKey.ToLocal(&key) || !object->Has(key)) | |
| 229 continue; | 243 continue; |
| 230 | 244 |
| 231 v8::Local<v8::Value> value = options->Get(key); | 245 v8::Local<v8::Value> value = object->Get(key); |
| 246 if (value.IsEmpty()) | |
| 247 continue; | |
| 232 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); | 248 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); |
| 233 TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false); | 249 TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false); |
| 234 if (!static_cast<const String&>(stringKey).isEmpty()) | 250 if (!static_cast<const String&>(stringKey).isEmpty()) |
| 235 hashMap.set(stringKey, stringValue); | 251 hashMap.set(stringKey, stringValue); |
| 236 } | 252 } |
| 237 | 253 |
| 238 return true; | 254 return true; |
| 239 } | 255 } |
| 240 | 256 |
| 241 bool Dictionary::getPropertyNames(Vector<String>& names) const | 257 bool Dictionary::getPropertyNames(Vector<String>& names) const |
| 242 { | 258 { |
| 243 if (!isObject()) | 259 if (!isObject()) |
| 244 return false; | 260 return false; |
| 245 | 261 |
| 246 v8::Handle<v8::Object> options = m_options->ToObject(m_isolate); | 262 v8::Local<v8::Object> object; |
| 247 if (options.IsEmpty()) | 263 TO_OBJECT_WITH_CHECK(m_context, m_options, object); |
| 248 return false; | |
| 249 | 264 |
| 250 v8::Local<v8::Array> properties = options->GetPropertyNames(); | 265 v8::Local<v8::Array> properties = object->GetPropertyNames(); |
| 251 if (properties.IsEmpty()) | 266 if (properties.IsEmpty()) |
| 252 return true; | 267 return true; |
| 253 for (uint32_t i = 0; i < properties->Length(); ++i) { | 268 for (uint32_t i = 0; i < properties->Length(); ++i) { |
| 254 v8::Local<v8::String> key = properties->Get(i)->ToString(m_isolate); | 269 v8::Local<v8::Value> property = properties->Get(i); |
| 255 if (!options->Has(key)) | 270 if (property.IsEmpty()) |
| 271 continue; | |
| 272 v8::MaybeLocal<v8::String> maybeKey = properties->Get(i)->ToString(m_con text); | |
| 273 v8::Local<v8::String> key; | |
| 274 if (!maybeKey.ToLocal(&key) || !object->Has(key)) | |
| 256 continue; | 275 continue; |
| 257 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); | 276 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); |
| 258 names.append(stringKey); | 277 names.append(stringKey); |
| 259 } | 278 } |
| 260 | 279 |
| 261 return true; | 280 return true; |
| 262 } | 281 } |
| 263 | 282 |
| 264 void Dictionary::ConversionContext::resetPerPropertyContext() | 283 void Dictionary::ConversionContext::resetPerPropertyContext() |
| 265 { | 284 { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 278 m_propertyTypeName = typeName; | 297 m_propertyTypeName = typeName; |
| 279 | 298 |
| 280 return *this; | 299 return *this; |
| 281 } | 300 } |
| 282 | 301 |
| 283 void Dictionary::ConversionContext::throwTypeError(const String& detail) | 302 void Dictionary::ConversionContext::throwTypeError(const String& detail) |
| 284 { | 303 { |
| 285 exceptionState().throwTypeError(detail); | 304 exceptionState().throwTypeError(detail); |
| 286 } | 305 } |
| 287 | 306 |
| 307 void Dictionary::willDisposeScriptState(ScriptState*) | |
| 308 { | |
| 309 m_context.Clear(); | |
| 310 } | |
| 311 | |
| 312 void Dictionary::subscribeScriptStateDisposal() | |
| 313 { | |
| 314 if (m_isolate) { | |
| 315 ScriptState* scriptState = ScriptState::current(m_isolate); | |
| 316 scriptState->addObserver(this); | |
| 317 m_context = scriptState->context(); | |
| 318 ASSERT(!m_context.IsEmpty()); | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 void Dictionary::unsubscribeScriptStateDisposal() | |
| 323 { | |
| 324 if (m_isolate) { | |
| 325 ScriptState* scriptState = ScriptState::current(m_isolate); | |
| 326 scriptState->removeObserver(this); | |
| 327 } | |
| 328 } | |
| 329 | |
| 288 } // namespace blink | 330 } // namespace blink |
| OLD | NEW |