5c1d7a150b54880dad18a37ae184a626172f0c20
[WebKit-https.git] / WebKit / win / WebScriptScope.cpp
1 /*
2  * Copyright (C) 2007 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "WebKitDLL.h"
31 #include "WebScriptScope.h"
32
33 #include "WebScriptCallFrame.h"
34
35 #include <memory>
36 #include <JavaScriptCore/PropertyNameArray.h>
37 #include <wtf/Assertions.h>
38 #include <wtf/OwnPtr.h>
39
40 #pragma warning(push, 0)
41 #include <WebCore/BString.h>
42 #include <WebCore/PlatformString.h>
43 #pragma warning(pop)
44
45 using namespace KJS;
46 using namespace std;
47
48 // EnumVariables -----------------------------------------------------------------
49
50 class EnumVariables : public IEnumVARIANT {
51 public:
52     static EnumVariables* createInstance(auto_ptr<PropertyNameArray>);
53
54 private:
55     EnumVariables(auto_ptr<PropertyNameArray> variableNames)
56         : m_refCount(0)
57         , m_names(variableNames.release())
58         , m_current(m_names->begin())
59     {
60     }
61
62 public:
63     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void** ppvObject);
64     virtual ULONG STDMETHODCALLTYPE AddRef();
65     virtual ULONG STDMETHODCALLTYPE Release();
66     virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched);
67     virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);
68     virtual HRESULT STDMETHODCALLTYPE Reset(void);
69     virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT**);
70
71 private:
72     ULONG m_refCount;
73     OwnPtr<PropertyNameArray> m_names;
74     PropertyNameArrayIterator m_current;
75 };
76
77 EnumVariables* EnumVariables::createInstance(auto_ptr<PropertyNameArray> variableNames)
78 {
79     EnumVariables* instance = new EnumVariables(variableNames);
80     instance->AddRef();
81     return instance;
82 }
83
84 HRESULT STDMETHODCALLTYPE EnumVariables::QueryInterface(REFIID riid, void** ppvObject)
85 {
86     *ppvObject = 0;
87     if (IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IEnumVARIANT))
88         *ppvObject = this;
89     else
90         return E_NOINTERFACE;
91
92     AddRef();
93     return S_OK;
94 }
95
96 ULONG STDMETHODCALLTYPE EnumVariables::AddRef()
97 {
98     return ++m_refCount;
99 }
100
101 ULONG STDMETHODCALLTYPE EnumVariables::Release()
102 {
103     ULONG newRef = --m_refCount;
104     if (!newRef)
105         delete(this);
106     return newRef;
107 }
108
109 HRESULT STDMETHODCALLTYPE EnumVariables::Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched)
110 {
111     if (pCeltFetched)
112         *pCeltFetched = 0;
113     if (!rgVar)
114         return E_POINTER;
115     VariantInit(rgVar);
116     if (!celt || celt > 1)
117         return S_FALSE;
118     if (m_current == m_names->end())
119         return S_FALSE;
120
121     V_VT(rgVar) = VT_BSTR;
122     V_BSTR(rgVar) = WebCore::BString(*m_current).release();
123     ++m_current;
124
125     if (pCeltFetched)
126         *pCeltFetched = 1;
127     return S_OK;
128 }
129
130 HRESULT STDMETHODCALLTYPE EnumVariables::Skip(ULONG celt)
131 {
132     for (ULONG i = 0; i < celt; ++i)
133         ++m_current;
134     return (m_current != m_names->end()) ? S_OK : S_FALSE;
135 }
136
137 HRESULT STDMETHODCALLTYPE EnumVariables::Reset(void)
138 {
139     m_current = 0;
140     return S_OK;
141 }
142
143 HRESULT STDMETHODCALLTYPE EnumVariables::Clone(IEnumVARIANT**)
144 {
145     return E_NOTIMPL;
146 }
147
148 // WebScriptScope ------------------------------------------------------------
149
150 WebScriptScope::WebScriptScope(JSObject* scope)
151     : m_refCount(0)
152     , m_scope(scope)
153 {
154     gClassCount++;
155 }
156
157 WebScriptScope::~WebScriptScope()
158 {
159     gClassCount--;
160 }
161
162 WebScriptScope* WebScriptScope::createInstance(JSObject* scope)
163 {
164     WebScriptScope* instance = new WebScriptScope(scope);
165     instance->AddRef();
166     return instance;
167 }
168
169 // IUnknown -------------------------------------------------------------------
170
171 HRESULT STDMETHODCALLTYPE WebScriptScope::QueryInterface(REFIID riid, void** ppvObject)
172 {
173     *ppvObject = 0;
174     if (IsEqualGUID(riid, IID_IUnknown))
175         *ppvObject = static_cast<IWebScriptScope*>(this);
176     else if (IsEqualGUID(riid, IID_IWebScriptScope))
177         *ppvObject = static_cast<IWebScriptScope*>(this);
178     else
179         return E_NOINTERFACE;
180
181     AddRef();
182     return S_OK;
183 }
184
185 ULONG STDMETHODCALLTYPE WebScriptScope::AddRef(void)
186 {
187     return ++m_refCount;
188 }
189
190 ULONG STDMETHODCALLTYPE WebScriptScope::Release(void)
191 {
192     ULONG newRef = --m_refCount;
193     if (!newRef)
194         delete(this);
195
196     return newRef;
197 }
198
199 // WebScriptScope ------------------------------------------------------------
200
201 HRESULT STDMETHODCALLTYPE WebScriptScope::variableNames(
202     /* [in] */ IWebScriptCallFrame* frame,
203     /* [out, retval] */ IEnumVARIANT** variableNames)
204 {
205     if (!frame)
206         return E_FAIL;
207
208     if (!variableNames)
209         return E_POINTER;
210
211     *variableNames = 0;
212
213     auto_ptr<PropertyNameArray> props(new PropertyNameArray);
214     m_scope->getPropertyNames(frame->impl()->state(), *(props.get()));
215
216     *variableNames = EnumVariables::createInstance(props);
217
218     return S_OK;
219 }
220
221 HRESULT STDMETHODCALLTYPE WebScriptScope::valueForVariable(
222     /* [in] */ IWebScriptCallFrame* frame,
223     /* [in] */ BSTR key,
224     /* [out, retval] */ BSTR* value)
225 {
226     if (!frame || !key)
227         return E_FAIL;
228
229     if (!value)
230         return E_POINTER;
231
232     *value = 0;
233
234     Identifier identKey(reinterpret_cast<KJS::UChar*>(key), SysStringLen(key));
235
236     JSValue* jsvalue = m_scope->get(frame->impl()->state(), identKey);
237
238     UString string;
239     const JSType type = jsvalue->type();
240     switch (type) {
241         case NullType:
242         case UndefinedType:
243         case UnspecifiedType:
244         case GetterSetterType:
245             break;
246         case StringType:
247             string = jsvalue->getString();
248             break;
249         case NumberType:
250             string = UString::from(jsvalue->getNumber());
251             break;
252         case BooleanType:
253             string = jsvalue->getBoolean() ? "True" : "False";
254             break;
255         case ObjectType: {
256             JSObject* jsobject = jsvalue->getObject();
257             jsvalue = jsobject->defaultValue(frame->impl()->state(), StringType);
258             string = jsvalue->getString();
259             break;
260         }
261     }
262
263     *value = WebCore::BString(string).release();
264     return S_OK;
265 }