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 CANON INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CANON INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "JSDOMMapLike.h"
28
29#include "WebCoreJSClientData.h"
30#include <JavaScriptCore/CatchScope.h>
31
32namespace WebCore {
33
34static inline JSC::JSObject& getBackingMap(JSC::ExecState& state, JSC::JSObject& mapLike)
35{
36 auto& vm = state.vm();
37 auto backingMap = mapLike.get(&state, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().backingMapPrivateName());
38 return *JSC::asObject(backingMap);
39}
40
41void initializeBackingMap(JSC::VM& vm, JSC::JSObject& mapLike, JSC::JSMap& backingMap)
42{
43 mapLike.putDirect(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().backingMapPrivateName(), &backingMap, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum));
44}
45
46JSC::JSMap& createBackingMap(JSC::ExecState& state, JSC::JSGlobalObject& globalObject, JSC::JSObject& mapLike)
47{
48 auto& vm = state.vm();
49 auto scope = DECLARE_CATCH_SCOPE(vm);
50
51 ASSERT(mapLike.get(&state, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().backingMapPrivateName()).isUndefined());
52 auto backingMap = JSC::JSMap::create(&state, vm, globalObject.mapStructure());
53 scope.releaseAssertNoException();
54 mapLike.putDirect(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().backingMapPrivateName(), backingMap, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum));
55 return *backingMap;
56}
57
58JSC::JSValue forwardAttributeGetterToBackingMap(JSC::ExecState& state, JSC::JSObject& mapLike, const JSC::Identifier& attributeName)
59{
60 return getBackingMap(state, mapLike).get(&state, attributeName);
61}
62
63JSC::JSValue forwardFunctionCallToBackingMap(JSC::ExecState& state, JSC::JSObject& mapLike, const JSC::Identifier& functionName)
64{
65 auto& backingMap = getBackingMap(state, mapLike);
66
67 JSC::JSValue function = backingMap.get(&state, functionName);
68 ASSERT(function);
69
70 JSC::CallData callData;
71 JSC::CallType callType = JSC::getCallData(state.vm(), function, callData);
72 ASSERT(callType != JSC::CallType::None);
73 JSC::MarkedArgumentBuffer arguments;
74 for (size_t cptr = 0; cptr < state.argumentCount(); ++cptr)
75 arguments.append(state.uncheckedArgument(cptr));
76 ASSERT(!arguments.hasOverflowed());
77 return JSC::call(&state, function, callType, callData, &backingMap, arguments);
78}
79
80JSC::JSValue forwardForEachCallToBackingMap(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::JSObject& mapLike)
81{
82 auto* function = globalObject.builtinInternalFunctions().jsDOMBindingInternals().m_mapLikeForEachFunction.get();
83 ASSERT(function);
84
85 getBackingMap(state, mapLike);
86
87 JSC::CallData callData;
88 JSC::CallType callType = JSC::getCallData(state.vm(), function, callData);
89 ASSERT(callType != JSC::CallType::None);
90 JSC::MarkedArgumentBuffer arguments;
91 for (size_t cptr = 0; cptr < state.argumentCount(); ++cptr)
92 arguments.append(state.uncheckedArgument(cptr));
93 ASSERT(!arguments.hasOverflowed());
94 return JSC::call(&state, function, callType, callData, &mapLike, arguments);
95}
96
97}
98