Stop placing std::isfinite and std::signbit inside the global scope
[WebKit.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 "CachedScript.h"
26 #include "DOMObjectHashTableMap.h"
27 #include "DOMStringList.h"
28 #include "ExceptionCode.h"
29 #include "ExceptionHeaders.h"
30 #include "ExceptionInterfaces.h"
31 #include "Frame.h"
32 #include "JSDOMWindowCustom.h"
33 #include "JSExceptionBase.h"
34 #include "ScriptCallStack.h"
35 #include <interpreter/Interpreter.h>
36 #include <runtime/DateInstance.h>
37 #include <runtime/Error.h>
38 #include <runtime/ExceptionHelpers.h>
39 #include <runtime/JSFunction.h>
40
41 using namespace JSC;
42
43 namespace WebCore {
44
45 ASSERT_HAS_TRIVIAL_DESTRUCTOR(DOMConstructorObject);
46 ASSERT_HAS_TRIVIAL_DESTRUCTOR(DOMConstructorWithDocument);
47
48 const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable)
49 {
50     return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);
51 }
52
53 JSValue jsStringOrNull(ExecState* exec, const String& s)
54 {
55     if (s.isNull())
56         return jsNull();
57     return jsStringWithCache(exec, s);
58 }
59
60 JSValue jsOwnedStringOrNull(ExecState* exec, const String& s)
61 {
62     if (s.isNull())
63         return jsNull();
64     return jsOwnedString(exec, s);
65 }
66
67 JSValue jsStringOrUndefined(ExecState* exec, const String& s)
68 {
69     if (s.isNull())
70         return jsUndefined();
71     return jsStringWithCache(exec, s);
72 }
73
74 JSValue jsString(ExecState* exec, const KURL& url)
75 {
76     return jsStringWithCache(exec, url.string());
77 }
78
79 JSValue jsStringOrNull(ExecState* exec, const KURL& url)
80 {
81     if (url.isNull())
82         return jsNull();
83     return jsStringWithCache(exec, url.string());
84 }
85
86 JSValue jsStringOrUndefined(ExecState* exec, const KURL& url)
87 {
88     if (url.isNull())
89         return jsUndefined();
90     return jsStringWithCache(exec, url.string());
91 }
92
93 AtomicStringImpl* findAtomicString(PropertyName propertyName)
94 {
95     StringImpl* impl = propertyName.publicName();
96     if (!impl)
97         return 0;
98     ASSERT(impl->existingHash());
99     return AtomicString::find(impl);
100 }
101
102 String valueToStringWithNullCheck(ExecState* exec, JSValue value)
103 {
104     if (value.isNull())
105         return String();
106     return value.toString(exec)->value(exec);
107 }
108
109 String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
110 {
111     if (value.isUndefinedOrNull())
112         return String();
113     return value.toString(exec)->value(exec);
114 }
115
116 JSValue jsDateOrNull(ExecState* exec, double value)
117 {
118     if (!std::isfinite(value))
119         return jsNull();
120     return DateInstance::create(exec, exec->lexicalGlobalObject()->dateStructure(), value);
121 }
122
123 double valueToDate(ExecState* exec, JSValue value)
124 {
125     if (value.isNumber())
126         return value.asNumber();
127     if (!value.inherits(&DateInstance::s_info))
128         return std::numeric_limits<double>::quiet_NaN();
129     return static_cast<DateInstance*>(value.toObject(exec))->internalNumber();
130 }
131
132 JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<DOMStringList> stringList)
133 {
134     JSC::MarkedArgumentBuffer list;
135     if (stringList) {
136         for (unsigned i = 0; i < stringList->length(); ++i)
137             list.append(jsStringWithCache(exec, stringList->item(i)));
138     }
139     return JSC::constructArray(exec, 0, globalObject, list);
140 }
141
142 void reportException(ExecState* exec, JSValue exception, CachedScript* cachedScript)
143 {
144     if (isTerminatedExecutionException(exception))
145         return;
146
147     Interpreter::ErrorHandlingMode mode(exec);
148     String errorMessage = exception.toString(exec)->value(exec);
149     JSObject* exceptionObject = exception.toObject(exec);
150     int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec);
151     String exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL")).toString(exec)->value(exec);
152     exec->clearException();
153
154     if (ExceptionBase* exceptionBase = toExceptionBase(exception))
155         errorMessage = exceptionBase->message() + ": "  + exceptionBase->description();
156
157     JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
158     if (JSDOMWindow* window = jsDynamicCast<JSDOMWindow*>(globalObject)) {
159         if (!window->impl()->isCurrentlyDisplayedInFrame())
160             return;
161     }
162     ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();
163     scriptExecutionContext->reportException(errorMessage, lineNumber, exceptionSourceURL, 0, cachedScript);
164 }
165
166 void reportCurrentException(ExecState* exec)
167 {
168     JSValue exception = exec->exception();
169     exec->clearException();
170     reportException(exec, exception);
171 }
172
173 #define TRY_TO_CREATE_EXCEPTION(interfaceName) \
174     case interfaceName##Type: \
175         errorObject = toJS(exec, globalObject, interfaceName::create(description)); \
176         break;
177
178 void setDOMException(ExecState* exec, ExceptionCode ec)
179 {
180     if (!ec || exec->hadException())
181         return;
182
183     // FIXME: Handle other WebIDL exception types.
184     if (ec == TypeError) {
185         throwTypeError(exec);
186         return;
187     }
188
189     // FIXME: All callers to setDOMException need to pass in the right global object
190     // for now, we're going to assume the lexicalGlobalObject.  Which is wrong in cases like this:
191     // frames[0].document.createElement(null, null); // throws an exception which should have the subframes prototypes.
192     JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec);
193
194     ExceptionCodeDescription description(ec);
195
196     JSValue errorObject;
197     switch (description.type) {
198         DOM_EXCEPTION_INTERFACES_FOR_EACH(TRY_TO_CREATE_EXCEPTION)
199     }
200
201     ASSERT(errorObject);
202     throwError(exec, errorObject);
203 }
204
205 #undef TRY_TO_CREATE_EXCEPTION
206
207 bool shouldAllowAccessToNode(ExecState* exec, Node* node)
208 {
209     return BindingSecurity::shouldAllowAccessToNode(exec, node);
210 }
211
212 bool shouldAllowAccessToFrame(ExecState* exec, Frame* target)
213 {
214     return BindingSecurity::shouldAllowAccessToFrame(exec, target);
215 }
216
217 bool shouldAllowAccessToFrame(ExecState* exec, Frame* frame, String& message)
218 {
219     if (!frame)
220         return false;
221     if (BindingSecurity::shouldAllowAccessToFrame(exec, frame, DoNotReportSecurityError))
222         return true;
223     message = frame->document()->domWindow()->crossDomainAccessErrorMessage(activeDOMWindow(exec));
224     return false;
225 }
226
227 bool shouldAllowAccessToDOMWindow(ExecState* exec, DOMWindow* target, String& message)
228 {
229     if (!target)
230         return false;
231     if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, target, DoNotReportSecurityError))
232         return true;
233     message = target->crossDomainAccessErrorMessage(activeDOMWindow(exec));
234     return false;
235 }
236
237 void printErrorMessageForFrame(Frame* frame, const String& message)
238 {
239     if (!frame)
240         return;
241     frame->document()->domWindow()->printErrorMessage(message);
242 }
243
244 JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, PropertyName propertyName)
245 {
246     return JSFunction::create(exec, exec->lexicalGlobalObject(), 0, propertyName.publicName(), objectProtoFuncToString);
247 }
248
249 Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo)
250 {
251     JSDOMStructureMap& structures = globalObject->structures();
252     return structures.get(classInfo).get();
253 }
254
255 Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, Structure* structure, const ClassInfo* classInfo)
256 {
257     JSDOMStructureMap& structures = globalObject->structures();
258     ASSERT(!structures.contains(classInfo));
259     return structures.set(classInfo, WriteBarrier<Structure>(globalObject->globalData(), globalObject, structure)).iterator->value.get();
260 }
261
262 } // namespace WebCore