JSValue JSMessageEvent::data(ExecState& state) const { if (JSValue cachedValue = m_data.get()) { // 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(&state)) return cachedValue; ASSERT_NOT_REACHED(); } MessageEvent& event = wrapped(); JSValue result; switch (event.dataType()) { case MessageEvent::DataTypeScriptValue: { JSValue dataValue = event.dataAsScriptValue(); if (!dataValue) result = jsNull(); else { // We need to make sure MessageEvents do not leak objects in their state property across isolated DOM worlds. // Ideally, we would check that the worlds have different privileges but that's not possible yet. if (dataValue.isObject() && &worldForDOMObject(dataValue.getObject()) != ¤tWorld(&state)) { RefPtr<SerializedScriptValue> serializedValue = event.trySerializeData(&state); if (serializedValue) result = serializedValue->deserialize(state, globalObject()); else result = jsNull(); } else result = dataValue; } break; } case MessageEvent::DataTypeSerializedScriptValue: if (RefPtr<SerializedScriptValue> serializedValue = event.dataAsSerializedScriptValue()) { Vector<RefPtr<MessagePort>> ports = wrapped().ports(); // FIXME: Why does this suppress exceptions? result = serializedValue->deserialize(state, globalObject(), ports, NonThrowing); } else result = jsNull(); break; case MessageEvent::DataTypeString: result = jsStringWithCache(&state, event.dataAsString()); break; case MessageEvent::DataTypeBlob: result = toJS(&state, globalObject(), event.dataAsBlob()); break; case MessageEvent::DataTypeArrayBuffer: result = toJS(&state, globalObject(), event.dataAsArrayBuffer()); break; } // Save the result so we don't have to deserialize the value again. m_data.set(state.vm(), this, result); return result; }
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); }
JSValue JSCustomEvent::detail(ExecState& state) const { auto& event = wrapped(); auto detail = event.detail(); if (!detail) return jsNull(); if (detail.isObject() && &worldForDOMObject(detail.getObject()) != ¤tWorld(&state)) { // We need to make sure CustomEvents do not leak their detail property across isolated DOM worlds. // Ideally, we would check that the worlds have different privileges but that's not possible yet. auto serializedDetail = event.trySerializeDetail(state); if (!serializedDetail) return jsNull(); return serializedDetail->deserialize(&state, globalObject(), nullptr); } return detail; }