Rename first/second to key/value in HashMap iterators
[WebKit-https.git] / Source / WebCore / bindings / js / JSDOMBinding.cpp
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4  *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "config.h"
22 #include "JSDOMBinding.h"
23
24 #include "BindingSecurity.h"
25 #include "DOMObjectHashTableMap.h"
26 #include "DOMStringList.h"
27 #include "ExceptionCode.h"
28 #include "ExceptionHeaders.h"
29 #include "ExceptionInterfaces.h"
30 #include "Frame.h"
31 #include "JSDOMWindowCustom.h"
32 #include "JSExceptionBase.h"
33 #include "ScriptCallStack.h"
34 #include <runtime/DateInstance.h>
35 #include <runtime/Error.h>
36 #include <runtime/ExceptionHelpers.h>
37 #include <runtime/JSFunction.h>
38
39 using namespace JSC;
40
41 namespace WebCore {
42
43 ASSERT_HAS_TRIVIAL_DESTRUCTOR(DOMConstructorObject);
44 ASSERT_HAS_TRIVIAL_DESTRUCTOR(DOMConstructorWithDocument);
45
46 const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable)
47 {
48     return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);
49 }
50
51 JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl* stringImpl)
52 {
53     JSString* wrapper = jsString(exec, UString(stringImpl));
54     weakAdd(stringCache, stringImpl, PassWeak<JSString>(wrapper, currentWorld(exec)->stringWrapperOwner(), stringImpl));
55     return wrapper;
56 }
57
58 JSValue jsStringOrNull(ExecState* exec, const String& s)
59 {
60     if (s.isNull())
61         return jsNull();
62     return jsString(exec, s);
63 }
64
65 JSValue jsOwnedStringOrNull(ExecState* exec, const String& s)
66 {
67     if (s.isNull())
68         return jsNull();
69     return jsOwnedString(exec, stringToUString(s));
70 }
71
72 JSValue jsStringOrUndefined(ExecState* exec, const String& s)
73 {
74     if (s.isNull())
75         return jsUndefined();
76     return jsString(exec, s);
77 }
78
79 JSValue jsString(ExecState* exec, const KURL& url)
80 {
81     return jsString(exec, url.string());
82 }
83
84 JSValue jsStringOrNull(ExecState* exec, const KURL& url)
85 {
86     if (url.isNull())
87         return jsNull();
88     return jsString(exec, url.string());
89 }
90
91 JSValue jsStringOrUndefined(ExecState* exec, const KURL& url)
92 {
93     if (url.isNull())
94         return jsUndefined();
95     return jsString(exec, url.string());
96 }
97
98 AtomicStringImpl* findAtomicString(PropertyName propertyName)
99 {
100     StringImpl* impl = propertyName.publicName();
101     if (!impl)
102         return 0;
103     ASSERT(impl->existingHash());
104     return AtomicString::find(impl);
105 }
106
107 String valueToStringWithNullCheck(ExecState* exec, JSValue value)
108 {
109     if (value.isNull())
110         return String();
111     return ustringToString(value.toString(exec)->value(exec));
112 }
113
114 String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
115 {
116     if (value.isUndefinedOrNull())
117         return String();
118     return ustringToString(value.toString(exec)->value(exec));
119 }
120
121 JSValue jsDateOrNull(ExecState* exec, double value)
122 {
123     if (!isfinite(value))
124         return jsNull();
125     return DateInstance::create(exec, exec->lexicalGlobalObject()->dateStructure(), value);
126 }
127
128 double valueToDate(ExecState* exec, JSValue value)
129 {
130     if (value.isNumber())
131         return value.asNumber();
132     if (!value.inherits(&DateInstance::s_info))
133         return std::numeric_limits<double>::quiet_NaN();
134     return static_cast<DateInstance*>(value.toObject(exec))->internalNumber();
135 }
136
137 JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<DOMStringList> stringList)
138 {
139     JSC::MarkedArgumentBuffer list;
140     if (stringList) {
141         for (unsigned i = 0; i < stringList->length(); ++i)
142             list.append(jsString(exec, stringList->item(i)));
143     }
144     return JSC::constructArray(exec, globalObject, list);
145 }
146
147 void reportException(ExecState* exec, JSValue exception)
148 {
149     if (isTerminatedExecutionException(exception))
150         return;
151
152     UString errorMessage = exception.toString(exec)->value(exec);
153     JSObject* exceptionObject = exception.toObject(exec);
154     int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec);
155     UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL")).toString(exec)->value(exec);
156     exec->clearException();
157
158     if (ExceptionBase* exceptionBase = toExceptionBase(exception))
159         errorMessage = stringToUString(exceptionBase->message() + ": "  + exceptionBase->description());
160
161     JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
162     if (JSDOMWindow* window = jsDynamicCast<JSDOMWindow*>(globalObject)) {
163         if (!window->impl()->isCurrentlyDisplayedInFrame())
164             return;
165     }
166     ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();
167     scriptExecutionContext->reportException(ustringToString(errorMessage), lineNumber, ustringToString(exceptionSourceURL), 0);
168 }
169
170 void reportCurrentException(ExecState* exec)
171 {
172     JSValue exception = exec->exception();
173     exec->clearException();
174     reportException(exec, exception);
175 }
176
177 #define TRY_TO_CREATE_EXCEPTION(interfaceName) \
178     case interfaceName##Type: \
179         errorObject = toJS(exec, globalObject, interfaceName::create(description)); \
180         break;
181
182 void setDOMException(ExecState* exec, ExceptionCode ec)
183 {
184     if (!ec || exec->hadException())
185         return;
186
187     if (ec == NATIVE_TYPE_ERR) {
188         throwTypeError(exec);
189         return;
190     }
191
192     // FIXME: All callers to setDOMException need to pass in the right global object
193     // for now, we're going to assume the lexicalGlobalObject.  Which is wrong in cases like this:
194     // frames[0].document.createElement(null, null); // throws an exception which should have the subframes prototypes.
195     JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec);
196
197     ExceptionCodeDescription description(ec);
198
199     JSValue errorObject;
200     switch (description.type) {
201         DOM_EXCEPTION_INTERFACES_FOR_EACH(TRY_TO_CREATE_EXCEPTION)
202     }
203
204     ASSERT(errorObject);
205     throwError(exec, errorObject);
206 }
207
208 #undef TRY_TO_CREATE_EXCEPTION
209
210 bool shouldAllowAccessToNode(ExecState* exec, Node* node)
211 {
212     return BindingSecurity::shouldAllowAccessToNode(exec, node);
213 }
214
215 bool shouldAllowAccessToFrame(ExecState* exec, Frame* target)
216 {
217     return BindingSecurity::shouldAllowAccessToFrame(exec, target);
218 }
219
220 bool shouldAllowAccessToFrame(ExecState* exec, Frame* frame, String& message)
221 {
222     if (!frame)
223         return false;
224     bool result = BindingSecurity::shouldAllowAccessToFrame(exec, frame, DoNotReportSecurityError);
225     // FIXME: The following line of code should move somewhere that it can be shared with immediatelyReportUnsafeAccessTo.
226     message = frame->document()->domWindow()->crossDomainAccessErrorMessage(activeDOMWindow(exec));
227     return result;
228 }
229
230 bool shouldAllowAccessToDOMWindow(ExecState* exec, DOMWindow* target, String& message)
231 {
232     if (!target)
233         return false;
234     bool result = BindingSecurity::shouldAllowAccessToDOMWindow(exec, target, DoNotReportSecurityError);
235     // FIXME: The following line of code should move somewhere that it can be shared with immediatelyReportUnsafeAccessTo.
236     message = target->crossDomainAccessErrorMessage(activeDOMWindow(exec));
237     return result;
238 }
239
240 void printErrorMessageForFrame(Frame* frame, const String& message)
241 {
242     if (!frame)
243         return;
244     frame->document()->domWindow()->printErrorMessage(message);
245 }
246
247 JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, PropertyName propertyName)
248 {
249     return JSFunction::create(exec, exec->lexicalGlobalObject(), 0, propertyName.publicName(), objectProtoFuncToString);
250 }
251
252 Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo)
253 {
254     JSDOMStructureMap& structures = globalObject->structures();
255     return structures.get(classInfo).get();
256 }
257
258 Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, Structure* structure, const ClassInfo* classInfo)
259 {
260     JSDOMStructureMap& structures = globalObject->structures();
261     ASSERT(!structures.contains(classInfo));
262     return structures.set(classInfo, WriteBarrier<Structure>(globalObject->globalData(), globalObject, structure)).iterator->value.get();
263 }
264
265 } // namespace WebCore