1/*
2 * Copyright (C) 2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#if ENABLE(SERVICE_WORKER)
29#include "JSExtendableMessageEvent.h"
30
31#include "JSDOMConstructor.h"
32#include "JSDOMConvertInterface.h"
33#include "JSDOMConvertStrings.h"
34
35namespace WebCore {
36
37using namespace JSC;
38
39JSC::EncodedJSValue constructJSExtendableMessageEvent(JSC::ExecState& state)
40{
41 VM& vm = state.vm();
42 auto throwScope = DECLARE_THROW_SCOPE(vm);
43 UNUSED_PARAM(throwScope);
44
45 auto* jsConstructor = jsCast<JSDOMConstructorBase*>(state.jsCallee());
46 ASSERT(jsConstructor);
47 if (UNLIKELY(state.argumentCount() < 1))
48 return throwVMError(&state, throwScope, createNotEnoughArgumentsError(&state));
49 auto type = convert<IDLDOMString>(state, state.uncheckedArgument(0));
50 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
51 auto eventInitDict = convert<IDLDictionary<ExtendableMessageEvent::Init>>(state, state.argument(1));
52 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
53
54 JSValue data = eventInitDict.data;
55 auto object = ExtendableMessageEvent::create(state, WTFMove(type), WTFMove(eventInitDict));
56 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
57
58 JSValue wrapper = toJSNewlyCreated<IDLInterface<ExtendableMessageEvent>>(state, *jsConstructor->globalObject(), WTFMove(object));
59
60 // Cache the JSValue passed in for data parameter in the wrapper so the getter returns the exact value
61 // it was initialized too. We do not store the JSValue in the implementation object to avoid leaks.
62 auto* jsMessageEvent = jsCast<JSExtendableMessageEvent*>(wrapper);
63 jsMessageEvent->m_data.set(state.vm(), jsMessageEvent, data);
64
65 return JSValue::encode(wrapper);
66}
67
68JSValue JSExtendableMessageEvent::data(ExecState& state) const
69{
70 if (JSValue cachedValue = m_data.get()) {
71 // We cannot use a cached object if we are in a different world than the one it was created in.
72 if (isWorldCompatible(state, cachedValue))
73 return cachedValue;
74 ASSERT_NOT_REACHED();
75 }
76
77 auto& event = wrapped();
78 JSValue result;
79 if (auto* serializedValue = event.data())
80 result = serializedValue->deserialize(state, globalObject(), event.ports(), SerializationErrorMode::NonThrowing);
81 else
82 result = jsNull();
83
84 // Save the result so we don't have to deserialize the value again.
85 m_data.set(state.vm(), this, result);
86 return result;
87}
88
89}
90
91#endif // ENABLE(SERVICE_WORKER)
92