void V8CustomEvent::detailAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { CustomEvent* event = V8CustomEvent::toNative(info.Holder()); v8::Handle<v8::Value> result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::detail(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, result); return; } if (!event->serializedDetail()) { // If we're in an isolated world and the event was created in the main world, // we need to find the 'detail' property on the main world wrapper and clone it. v8::Local<v8::Value> mainWorldDetail = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::detail(info.GetIsolate())); if (!mainWorldDetail.IsEmpty()) event->setSerializedDetail(SerializedScriptValue::createAndSwallowExceptions(mainWorldDetail, info.GetIsolate())); } if (event->serializedDetail()) { result = event->serializedDetail()->deserialize(); v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); return; } v8SetReturnValue(info, cacheState(info.Holder(), v8::Null(info.GetIsolate()), info.GetIsolate())); }
void V8PopStateEvent::stateAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { v8::Local<v8::Value> result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, result); return; } PopStateEvent* event = V8PopStateEvent::toImpl(info.Holder()); History* history = event->history(); if (!history || !event->serializedState()) { if (!event->serializedState()) { // If we're in an isolated world and the event was created in the main world, // we need to find the 'state' property on the main world wrapper and clone it. v8::Local<v8::Value> mainWorldState = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::state(info.GetIsolate())); if (!mainWorldState.IsEmpty()) event->setSerializedState(SerializedScriptValueFactory::instance().createAndSwallowExceptions(info.GetIsolate(), mainWorldState)); } if (event->serializedState()) result = event->serializedState()->deserialize(); else result = v8::Null(info.GetIsolate()); v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); return; } // There's no cached value from a previous invocation, nor a state value was provided by the // event, but there is a history object, so first we need to see if the state object has been // deserialized through the history object already. // The current history state object might've changed in the meantime, so we need to take care // of using the correct one, and always share the same deserialization with history.state. bool isSameState = history->isSameAsCurrentState(event->serializedState()); if (isSameState) { v8::Local<v8::Value> v8HistoryValue = toV8(history, info.Holder(), info.GetIsolate()); if (v8HistoryValue.IsEmpty()) return; v8::Local<v8::Object> v8History = v8HistoryValue.As<v8::Object>(); if (!history->stateChanged()) { result = V8HiddenValue::getHiddenValue(info.GetIsolate(), v8History, V8HiddenValue::state(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); return; } } result = event->serializedState()->deserialize(info.GetIsolate()); V8HiddenValue::setHiddenValue(info.GetIsolate(), v8History, V8HiddenValue::state(info.GetIsolate()), result); } else { result = event->serializedState()->deserialize(info.GetIsolate()); } v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); }
void V8PopStateEvent::stateAttributeGetterCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Local<v8::Value> result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, result); return; } PopStateEvent* event = V8PopStateEvent::toImpl(info.Holder()); History* history = event->history(); if (!history || !event->serializedState()) { // If the event doesn't have serializedState(), it means that the // event was initialized with PopStateEventInit. In such case, we need // to get a v8 value for the current world from state(). if (event->serializedState()) result = event->serializedState()->deserialize(); else result = event->state().v8ValueFor(ScriptState::current(info.GetIsolate())); if (result.IsEmpty()) result = v8::Null(info.GetIsolate()); v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); return; } // There's no cached value from a previous invocation, nor a state value was provided by the // event, but there is a history object, so first we need to see if the state object has been // deserialized through the history object already. // The current history state object might've changed in the meantime, so we need to take care // of using the correct one, and always share the same deserialization with history.state. bool isSameState = history->isSameAsCurrentState(event->serializedState()); if (isSameState) { v8::Local<v8::Value> v8HistoryValue = toV8(history, info.Holder(), info.GetIsolate()); if (v8HistoryValue.IsEmpty()) return; v8::Local<v8::Object> v8History = v8HistoryValue.As<v8::Object>(); if (!history->stateChanged()) { result = V8HiddenValue::getHiddenValue(info.GetIsolate(), v8History, V8HiddenValue::state(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); return; } } result = event->serializedState()->deserialize(info.GetIsolate()); V8HiddenValue::setHiddenValue(info.GetIsolate(), v8History, V8HiddenValue::state(info.GetIsolate()), result); } else { result = event->serializedState()->deserialize(info.GetIsolate()); } v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); }
JSValue JSPopStateEvent::state(ExecState* exec) const { JSValue cachedValue = m_state.get(); if (!cachedValue.isEmpty()) { // We cannot use a cached object if we are in a different world than the one it was created in. if (!cachedValue.isObject() || &worldForDOMObject(cachedValue.getObject()) == ¤tWorld(exec)) return cachedValue; ASSERT_NOT_REACHED(); } PopStateEvent& event = impl(); if (!event.state().hasNoValue()) { // We need to make sure a PopStateEvent does not leak objects in its state property across isolated DOM worlds. // Ideally, we would check that the worlds have different privileges but that's not possible yet. JSValue state = event.state().jsValue(); if (state.isObject() && &worldForDOMObject(state.getObject()) != ¤tWorld(exec)) { if (RefPtr<SerializedScriptValue> serializedValue = event.trySerializeState(exec)) state = serializedValue->deserialize(exec, globalObject(), nullptr); else state = jsNull(); } return cacheState(exec, const_cast<JSPopStateEvent*>(this), state); } History* history = event.history(); if (!history || !event.serializedState()) return cacheState(exec, const_cast<JSPopStateEvent*>(this), jsNull()); // There's no cached value from a previous invocation, nor a state value was provided by the // event, but there is a history object, so first we need to see if the state object has been // deserialized through the history object already. // The current history state object might've changed in the meantime, so we need to take care // of using the correct one, and always share the same deserialization with history.state. bool isSameState = history->isSameAsCurrentState(event.serializedState().get()); JSValue result; if (isSameState) { JSHistory* jsHistory = jsCast<JSHistory*>(toJS(exec, globalObject(), history).asCell()); result = jsHistory->state(exec); } else result = event.serializedState()->deserialize(exec, globalObject(), 0); return cacheState(exec, const_cast<JSPopStateEvent*>(this), result); }
v8::Handle<v8::Value> V8PopStateEvent::stateAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.PopStateEvent.state"); v8::Handle<v8::Value> result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::state()); if (!result.IsEmpty()) return result; PopStateEvent* event = V8PopStateEvent::toNative(info.Holder()); if (!event->state().hasNoValue()) return cacheState(info.Holder(), event->state().v8Value()); History* history = event->history(); if (!history || !event->serializedState()) return cacheState(info.Holder(), v8::Null(info.GetIsolate())); // There's no cached value from a previous invocation, nor a state value was provided by the // event, but there is a history object, so first we need to see if the state object has been // deserialized through the history object already. // The current history state object might've changed in the meantime, so we need to take care // of using the correct one, and always share the same deserialization with history.state. bool isSameState = history->isSameAsCurrentState(event->serializedState()); if (isSameState) { v8::Handle<v8::Object> v8History = toV8(history, info.Holder()->CreationContext(), info.GetIsolate()).As<v8::Object>(); if (!history->stateChanged()) { result = v8History->GetHiddenValue(V8HiddenPropertyName::state()); if (!result.IsEmpty()) return cacheState(info.Holder(), result); } result = event->serializedState()->deserialize(0, info.GetIsolate()); v8History->SetHiddenValue(V8HiddenPropertyName::state(), result); } else result = event->serializedState()->deserialize(0, info.GetIsolate()); return cacheState(info.Holder(), result); }
void V8CustomEvent::detailAttributeGetterCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { CustomEvent* event = V8CustomEvent::toImpl(info.Holder()); v8::Local<v8::Value> result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::detail(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, result); return; } // Be careful not to return a V8 value which is created in different world. v8::Local<v8::Value> detail; if (SerializedScriptValue* serializedValue = event->serializedDetail()) detail = serializedValue->deserialize(); else detail = event->detail().v8ValueFor(ScriptState::current(info.GetIsolate())); // |detail| should be null when it is an empty handle because its default value is null. if (detail.IsEmpty()) detail = v8::Null(info.GetIsolate()); v8SetReturnValue(info, cacheState(info.GetIsolate(), info.Holder(), detail)); }