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>
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.
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.
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
22 #include "JSDOMBinding.h"
24 #include "DOMObjectHashTableMap.h"
25 #include "ExceptionCode.h"
26 #include "ExceptionHeaders.h"
27 #include "ExceptionInterfaces.h"
29 #include "JSDOMWindowCustom.h"
30 #include "JSExceptionBase.h"
31 #if ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
32 #include "JSFileException.h"
33 #include "JSOperationNotAllowedException.h"
35 #if ENABLE(TIZEN_INDEXED_DATABASE)
36 #include "JSDOMStringList.h"
37 #include "JSIDBDatabaseException.h"
39 #include "JSRangeException.h"
40 #if ENABLE(SQL_DATABASE)
41 #include "JSSQLException.h"
44 #include "JSSVGException.h"
46 #include "JSXMLHttpRequestException.h"
48 #include "JSXPathException.h"
50 #include "OperationNotAllowedException.h"
51 #include "RangeException.h"
52 #include "SQLException.h"
53 #include "SVGException.h"
54 #include "ScriptCallStack.h"
55 #include <runtime/DateInstance.h>
56 #include <runtime/Error.h>
57 #include <runtime/ExceptionHelpers.h>
58 #include <runtime/JSFunction.h>
64 const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable)
66 return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);
69 JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl* stringImpl)
71 JSString* wrapper = jsString(exec, UString(stringImpl));
72 stringCache.add(stringImpl, Weak<JSString>(exec->globalData(), wrapper, currentWorld(exec)->stringWrapperOwner(), stringImpl));
76 JSValue jsStringOrNull(ExecState* exec, const String& s)
80 return jsString(exec, s);
83 JSValue jsOwnedStringOrNull(ExecState* exec, const String& s)
87 return jsOwnedString(exec, stringToUString(s));
90 JSValue jsStringOrUndefined(ExecState* exec, const String& s)
94 return jsString(exec, s);
97 JSValue jsStringOrFalse(ExecState* exec, const String& s)
100 return jsBoolean(false);
101 return jsString(exec, s);
104 JSValue jsString(ExecState* exec, const KURL& url)
106 return jsString(exec, url.string());
109 JSValue jsStringOrNull(ExecState* exec, const KURL& url)
113 return jsString(exec, url.string());
116 JSValue jsStringOrUndefined(ExecState* exec, const KURL& url)
119 return jsUndefined();
120 return jsString(exec, url.string());
123 JSValue jsStringOrFalse(ExecState* exec, const KURL& url)
126 return jsBoolean(false);
127 return jsString(exec, url.string());
130 AtomicStringImpl* findAtomicString(const Identifier& identifier)
132 if (identifier.isNull())
134 StringImpl* impl = identifier.impl();
135 ASSERT(impl->existingHash());
136 return AtomicString::find(impl->characters(), impl->length(), impl->existingHash());
139 String valueToStringWithNullCheck(ExecState* exec, JSValue value)
143 return ustringToString(value.toString(exec));
146 String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
148 if (value.isUndefinedOrNull())
150 return ustringToString(value.toString(exec));
153 JSValue jsDateOrNull(ExecState* exec, double value)
155 if (!isfinite(value))
157 return DateInstance::create(exec, exec->lexicalGlobalObject()->dateStructure(), value);
160 double valueToDate(ExecState* exec, JSValue value)
162 if (value.isNumber())
163 return value.asNumber();
164 if (!value.inherits(&DateInstance::s_info))
165 return std::numeric_limits<double>::quiet_NaN();
166 return static_cast<DateInstance*>(value.toObject(exec))->internalNumber();
169 void reportException(ExecState* exec, JSValue exception)
171 if (isTerminatedExecutionException(exception))
174 UString errorMessage = exception.toString(exec);
175 JSObject* exceptionObject = exception.toObject(exec);
176 int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec);
177 UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL")).toString(exec);
178 exec->clearException();
180 if (ExceptionBase* exceptionBase = toExceptionBase(exception))
181 errorMessage = stringToUString(exceptionBase->message() + ": " + exceptionBase->description());
183 ScriptExecutionContext* scriptExecutionContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();
184 ASSERT(scriptExecutionContext);
186 // Crash data indicates null-dereference crashes at this point in the Safari 4 Public Beta.
187 // It's harmless to return here without reporting the exception to the log and the debugger in this case.
188 if (!scriptExecutionContext)
191 scriptExecutionContext->reportException(ustringToString(errorMessage), lineNumber, ustringToString(exceptionSourceURL), 0);
194 void reportCurrentException(ExecState* exec)
196 JSValue exception = exec->exception();
197 exec->clearException();
198 reportException(exec, exception);
201 #define TRY_TO_CREATE_EXCEPTION(interfaceName) \
202 case interfaceName##Type: \
203 errorObject = toJS(exec, globalObject, interfaceName::create(description)); \
206 void setDOMException(ExecState* exec, ExceptionCode ec)
208 if (!ec || exec->hadException())
211 // FIXME: All callers to setDOMException need to pass in the right global object
212 // for now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this:
213 // frames[0].document.createElement(null, null); // throws an exception which should have the subframes prototypes.
214 JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec);
216 ExceptionCodeDescription description(ec);
219 switch (description.type) {
220 DOM_EXCEPTION_INTERFACES_FOR_EACH(TRY_TO_CREATE_EXCEPTION)
224 throwError(exec, errorObject);
227 #undef TRY_TO_CREATE_EXCEPTION
229 DOMWindow* activeDOMWindow(ExecState* exec)
231 return asJSDOMWindow(exec->lexicalGlobalObject())->impl();
234 DOMWindow* firstDOMWindow(ExecState* exec)
236 return asJSDOMWindow(exec->dynamicGlobalObject())->impl();
239 bool checkNodeSecurity(ExecState* exec, Node* node)
241 return node && allowsAccessFromFrame(exec, node->document()->frame());
244 bool allowsAccessFromFrame(ExecState* exec, Frame* frame)
248 JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec));
249 return window && window->allowsAccessFrom(exec);
252 bool allowsAccessFromFrame(ExecState* exec, Frame* frame, String& message)
256 JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec));
257 return window && window->allowsAccessFrom(exec, message);
260 void printErrorMessageForFrame(Frame* frame, const String& message)
264 frame->domWindow()->printErrorMessage(message);
267 // FIXME: We should remove or at least deprecate this function. Callers can use firstDOMWindow directly.
268 Frame* toDynamicFrame(ExecState* exec)
270 return firstDOMWindow(exec)->frame();
273 JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
275 return JSFunction::create(exec, exec->lexicalGlobalObject(), 0, propertyName, objectProtoFuncToString);
278 Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo)
280 JSDOMStructureMap& structures = globalObject->structures();
281 return structures.get(classInfo).get();
284 Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, Structure* structure, const ClassInfo* classInfo)
286 JSDOMStructureMap& structures = globalObject->structures();
287 ASSERT(!structures.contains(classInfo));
288 return structures.set(classInfo, WriteBarrier<Structure>(globalObject->globalData(), globalObject, structure)).first->second.get();
291 JSC::JSObject* toJSSequence(ExecState* exec, JSValue value, unsigned& length)
293 JSObject* object = value.getObject();
295 throwTypeError(exec);
298 JSValue lengthValue = object->get(exec, exec->propertyNames().length);
299 if (exec->hadException())
302 if (lengthValue.isUndefinedOrNull()) {
303 throwTypeError(exec);
307 length = lengthValue.toUInt32(exec);
308 if (exec->hadException())
314 #if ENABLE(TIZEN_INDEXED_DATABASE)
315 DOMStringList* jsValueToWebCoreDOMStringList(ExecState* exec, JSValue value)
317 if (value.inherits(&JSArray::s_info)) {
318 RefPtr<DOMStringList> strings = DOMStringList::create();
319 JSArray* jsArray = asArray(value);
320 for (int i = 0; i < jsArray->length(); i++) {
321 String string = valueToStringWithUndefinedOrNullCheck(exec, jsArray->pop());
322 strings->append(string);
324 return strings.release().leakRef();
326 return toDOMStringList(value);
328 #endif // TIZEN_INDEXED_DATABASE
330 } // namespace WebCore