JSValue JSPopStateEvent::state(ExecState* exec) const
{
    PopStateEvent* event = static_cast<PopStateEvent*>(impl());
    SerializedScriptValue* serializedState = event->serializedState();
    if (serializedState)
        return serializedState->deserialize(exec, globalObject(), 0);
    if (!event->state().hasNoValue())
        return event->state().jsValue();
    return jsNull();
}
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()));
}
JSValue JSPopStateEvent::initPopStateEvent(ExecState* exec, const ArgList& args)
{
    const UString& typeArg = args.at(0).toString(exec);
    bool canBubbleArg = args.at(1).toBoolean(exec);
    bool cancelableArg = args.at(2).toBoolean(exec);
    RefPtr<SerializedScriptValue> stateObjectArg = SerializedScriptValue::create(exec, args.at(3));
    
    PopStateEvent* event = static_cast<PopStateEvent*>(impl());
    event->initPopStateEvent(typeArg, canBubbleArg, cancelableArg, stateObjectArg.release());
    return jsUndefined();
}
v8::Handle<v8::Value> V8PopStateEvent::stateAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
{
    INC_STATS("DOM.PopStateEvent.state");

    PopStateEvent* event = V8PopStateEvent::toNative(info.Holder());
    SerializedScriptValue* state = event->state();
    if (!state)
        return v8::Null();

    return state->deserialize();
}
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()));
}
v8::Handle<v8::Value> V8PopStateEvent::initPopStateEventCallback(const v8::Arguments& args)
{
    INC_STATS("DOM.PopStateEvent.initPopStateEvent");

    String typeArg = v8ValueToWebCoreString(args[0]);
    bool canBubbleArg = args[1]->BooleanValue();
    bool cancelableArg = args[2]->BooleanValue();

    bool didThrow = false;
    RefPtr<SerializedScriptValue> stateArg = SerializedScriptValue::create(args[3], didThrow);
    if (didThrow)
        return v8::Undefined();

    PopStateEvent* event = V8PopStateEvent::toNative(args.Holder());
    event->initPopStateEvent(typeArg, canBubbleArg, cancelableArg, stateArg.release());

    return v8::Undefined();
}
Exemple #7
0
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);
}