2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 "debugger/DebuggerCallFrame.h"
26 #include "ActiveDOMObject.h"
27 #include "DOMCoreException.h"
28 #include "DOMObjectHashTableMap.h"
30 #include "EventException.h"
31 #include "ExceptionBase.h"
32 #include "ExceptionCode.h"
34 #include "HTMLAudioElement.h"
35 #include "HTMLCanvasElement.h"
36 #include "HTMLFrameElementBase.h"
37 #include "HTMLImageElement.h"
38 #include "HTMLLinkElement.h"
39 #include "HTMLNames.h"
40 #include "HTMLScriptElement.h"
41 #include "HTMLStyleElement.h"
42 #include "JSDOMCoreException.h"
43 #include "JSDOMWindowCustom.h"
44 #include "JSDebugWrapperSet.h"
45 #include "JSEventException.h"
46 #include "JSExceptionBase.h"
47 #include "JSMainThreadExecState.h"
49 #include "JSRangeException.h"
50 #include "JSXMLHttpRequestException.h"
52 #include "MessagePort.h"
53 #include "ProcessingInstruction.h"
54 #include "RangeException.h"
55 #include "ScriptCachedFrameData.h"
56 #include "ScriptCallStack.h"
57 #include "ScriptController.h"
59 #include "WebCoreJSClientData.h"
60 #include "XMLHttpRequestException.h"
61 #include <runtime/DateInstance.h>
62 #include <runtime/Error.h>
63 #include <runtime/JSFunction.h>
64 #include <runtime/PrototypeFunction.h>
65 #include <wtf/MathExtras.h>
66 #include <wtf/StdLibExtras.h>
69 #include "JSSVGException.h"
70 #include "SVGException.h"
74 #include "JSXPathException.h"
75 #include "XPathException.h"
79 #include "JSSQLException.h"
80 #include "SQLException.h"
83 #if ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
84 #include "FileException.h"
85 #include "JSFileException.h"
88 #if ENABLE(INDEXED_DATABASE)
89 #include "IDBDatabaseException.h"
90 #include "JSIDBDatabaseException.h"
97 using namespace HTMLNames;
99 typedef Document::JSWrapperCache JSWrapperCache;
100 typedef Document::JSWrapperCacheMap JSWrapperCacheMap;
102 class JSGlobalDataWorldIterator {
104 JSGlobalDataWorldIterator(JSGlobalData* globalData)
105 : m_pos(static_cast<WebCoreJSClientData*>(globalData->clientData)->m_worldSet.begin())
106 , m_end(static_cast<WebCoreJSClientData*>(globalData->clientData)->m_worldSet.end())
112 return m_pos != m_end;
115 DOMWrapperWorld* operator*()
117 ASSERT(m_pos != m_end);
121 DOMWrapperWorld* operator->()
123 ASSERT(m_pos != m_end);
127 JSGlobalDataWorldIterator& operator++()
134 HashSet<DOMWrapperWorld*>::iterator m_pos;
135 HashSet<DOMWrapperWorld*>::iterator m_end;
138 const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable)
140 return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);
143 bool hasCachedDOMObjectWrapperUnchecked(JSGlobalData* globalData, void* objectHandle)
145 for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
146 if (worldIter->m_wrappers.uncheckedGet(objectHandle))
152 bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle)
154 for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
155 if (worldIter->m_wrappers.get(objectHandle))
161 DOMObject* getCachedDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle)
163 return domObjectWrapperMapFor(exec).get(objectHandle);
166 void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject* wrapper)
168 JSDebugWrapperSet::willCacheWrapper(wrapper);
169 domObjectWrapperMapFor(exec).set(objectHandle, wrapper);
172 bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node)
175 return hasCachedDOMObjectWrapperUnchecked(JSDOMWindow::commonJSGlobalData(), node);
177 JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
178 for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
179 if (iter->second->uncheckedGet(node))
185 void forgetDOMObject(DOMObject* wrapper, void* objectHandle)
187 JSC::JSGlobalData* globalData = Heap::heap(wrapper)->globalData();
189 // Check the normal world first!
190 JSGlobalData::ClientData* clientData = globalData->clientData;
192 DOMObjectWrapperMap& wrappers = static_cast<WebCoreJSClientData*>(clientData)->normalWorld()->m_wrappers;
193 if (wrappers.uncheckedRemove(objectHandle, wrapper)) {
194 JSDebugWrapperSet::didUncacheWrapper(wrapper);
198 // We can't guarantee that a wrapper is in the cache when it uncaches itself,
199 // since a new wrapper may be cached before the old wrapper's destructor runs.
200 for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
201 if (worldIter->m_wrappers.uncheckedRemove(objectHandle, wrapper))
204 JSDebugWrapperSet::didUncacheWrapper(wrapper);
207 void forgetDOMNode(JSNode* wrapper, Node* node, Document* document)
209 node->clearWrapper(wrapper);
212 forgetDOMObject(wrapper, node);
216 // We can't guarantee that a wrapper is in the cache when it uncaches itself,
217 // since a new wrapper may be cached before the old wrapper's destructor runs.
218 JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
219 for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) {
220 if (wrappersIter->second->uncheckedRemove(node, wrapper))
223 JSDebugWrapperSet::didUncacheWrapper(wrapper);
226 void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper)
228 JSDebugWrapperSet::willCacheWrapper(wrapper);
231 domObjectWrapperMapFor(exec).set(node, wrapper);
233 document->getWrapperCache(currentWorld(exec))->set(node, wrapper);
235 if (currentWorld(exec)->isNormal())
236 node->setWrapper(wrapper);
239 static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world)
241 // Certain conditions implicitly make existence of a JS DOM node wrapper observable
242 // through the DOM, even if no explicit reference to it remains.
244 Node* node = jsNode->impl();
246 if (node->inDocument()) {
247 // If a node is in the document, and its wrapper has custom properties,
248 // the wrapper is observable because future access to the node through the
249 // DOM must reflect those properties.
250 if (jsNode->hasCustomProperties())
253 // If a node is in the document, and has event listeners, its wrapper is
254 // observable because its wrapper is responsible for marking those event listeners.
255 if (node->hasEventListeners())
256 return true; // Technically, we may overzealously mark a wrapper for a node that has only non-JS event listeners. Oh well.
258 // If a node owns another object with a wrapper with custom properties,
259 // the wrapper must be treated as observable, because future access to
260 // those objects through the DOM must reflect those properties.
261 // FIXME: It would be better if this logic could be in the node next to
262 // the custom markChildren functions rather than here.
263 // Note that for some compound objects like stylesheets and CSSStyleDeclarations,
264 // we don't descend to check children for custom properties, and just conservatively
265 // keep the node wrappers protecting them alive.
266 if (node->isElementNode()) {
267 if (NamedNodeMap* attributes = static_cast<Element*>(node)->attributeMap()) {
268 if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(attributes)) {
269 // FIXME: This check seems insufficient, because NamedNodeMap items can have custom properties themselves.
270 // Maybe it would be OK to just keep the wrapper alive, as it is done for CSSOM objects below.
271 if (wrapper->hasCustomProperties())
275 if (node->isStyledElement()) {
276 if (CSSMutableStyleDeclaration* style = static_cast<StyledElement*>(node)->inlineStyleDecl()) {
277 if (world->m_wrappers.uncheckedGet(style))
281 if (static_cast<Element*>(node)->hasTagName(canvasTag)) {
282 if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) {
283 if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(context)) {
284 if (wrapper->hasCustomProperties())
288 } else if (static_cast<Element*>(node)->hasTagName(linkTag)) {
289 if (StyleSheet* sheet = static_cast<HTMLLinkElement*>(node)->sheet()) {
290 if (world->m_wrappers.uncheckedGet(sheet))
293 } else if (static_cast<Element*>(node)->hasTagName(styleTag)) {
294 if (StyleSheet* sheet = static_cast<HTMLStyleElement*>(node)->sheet()) {
295 if (world->m_wrappers.uncheckedGet(sheet))
299 } else if (node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
300 if (StyleSheet* sheet = static_cast<ProcessingInstruction*>(node)->sheet()) {
301 if (world->m_wrappers.uncheckedGet(sheet))
306 // If a wrapper is the last reference to an image or script element
307 // that is loading but not in the document, the wrapper is observable
308 // because it is the only thing keeping the image element alive, and if
309 // the image element is destroyed, its load event will not fire.
310 // FIXME: The DOM should manage this issue without the help of JavaScript wrappers.
311 if (node->hasTagName(imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())
313 if (node->hasTagName(scriptTag) && !static_cast<HTMLScriptElement*>(node)->haveFiredLoadEvent())
316 if (node->hasTagName(audioTag) && !static_cast<HTMLAudioElement*>(node)->paused())
321 // If a node is firing event listeners, its wrapper is observable because
322 // its wrapper is responsible for marking those event listeners.
323 if (node->isFiringEventListeners())
329 void markDOMNodesForDocument(MarkStack& markStack, Document* document)
331 JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
332 for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) {
333 DOMWrapperWorld* world = wrappersIter->first;
334 JSWrapperCache* nodeDict = wrappersIter->second;
336 JSWrapperCache::iterator nodeEnd = nodeDict->uncheckedEnd();
337 for (JSWrapperCache::iterator nodeIt = nodeDict->uncheckedBegin(); nodeIt != nodeEnd; ++nodeIt) {
338 JSNode* jsNode = nodeIt->second;
339 if (isObservableThroughDOM(jsNode, world))
340 markStack.append(jsNode);
345 void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, ScriptExecutionContext* scriptExecutionContext)
347 // If an element has pending activity that may result in event listeners being called
348 // (e.g. an XMLHttpRequest), we need to keep JS wrappers alive.
350 const HashMap<ActiveDOMObject*, void*>& activeObjects = scriptExecutionContext->activeDOMObjects();
351 HashMap<ActiveDOMObject*, void*>::const_iterator activeObjectsEnd = activeObjects.end();
352 for (HashMap<ActiveDOMObject*, void*>::const_iterator iter = activeObjects.begin(); iter != activeObjectsEnd; ++iter) {
353 if (iter->first->hasPendingActivity()) {
354 // Generally, an active object with pending activity must have a wrapper to mark its listeners.
355 // However, some ActiveDOMObjects don't have JS wrappers.
356 markDOMObjectWrapper(markStack, globalData, iter->second);
360 const HashSet<MessagePort*>& messagePorts = scriptExecutionContext->messagePorts();
361 HashSet<MessagePort*>::const_iterator portsEnd = messagePorts.end();
362 for (HashSet<MessagePort*>::const_iterator iter = messagePorts.begin(); iter != portsEnd; ++iter) {
363 // If the message port is remotely entangled, then always mark it as in-use because we can't determine reachability across threads.
364 if (!(*iter)->locallyEntangledPort() || (*iter)->hasPendingActivity())
365 markDOMObjectWrapper(markStack, globalData, *iter);
369 typedef std::pair<JSNode*, DOMWrapperWorld*> WrapperAndWorld;
370 typedef WTF::Vector<WrapperAndWorld, 8> WrapperSet;
372 static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrapperSet)
375 JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
376 for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
377 if (JSNode* wrapper = iter->second->take(node)) {
378 JSDebugWrapperSet::didUncacheWrapper(wrapper);
379 wrapperSet.append(WrapperAndWorld(wrapper, iter->first));
383 for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) {
384 DOMWrapperWorld* world = *worldIter;
385 if (JSNode* wrapper = static_cast<JSNode*>(world->m_wrappers.take(node))) {
386 JSDebugWrapperSet::didUncacheWrapper(wrapper);
387 wrapperSet.append(WrapperAndWorld(wrapper, world));
393 void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocument)
395 ASSERT(oldDocument != newDocument);
397 WrapperSet wrapperSet;
398 takeWrappers(node, oldDocument, wrapperSet);
400 for (unsigned i = 0; i < wrapperSet.size(); ++i) {
401 JSNode* wrapper = wrapperSet[i].first;
402 JSDebugWrapperSet::willCacheWrapper(wrapper);
404 newDocument->getWrapperCache(wrapperSet[i].second)->set(node, wrapper);
406 wrapperSet[i].second->m_wrappers.set(node, wrapper);
410 void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* object)
412 // FIXME: This could be changed to only mark wrappers that are "observable"
413 // as markDOMNodesForDocument does, allowing us to collect more wrappers,
414 // but doing this correctly would be challenging.
418 for (JSGlobalDataWorldIterator worldIter(&globalData); worldIter; ++worldIter) {
419 if (DOMObject* wrapper = worldIter->m_wrappers.uncheckedGet(object))
420 markStack.append(wrapper);
424 void markDOMNodeWrapper(MarkStack& markStack, Document* document, Node* node)
427 JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
428 for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
429 if (JSNode* wrapper = iter->second->uncheckedGet(node))
430 markStack.append(wrapper);
435 for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) {
436 if (DOMObject* wrapper = worldIter->m_wrappers.uncheckedGet(node))
437 markStack.append(wrapper);
441 static void stringWrapperDestroyed(JSString* str, void* context)
443 StringImpl* cacheKey = static_cast<StringImpl*>(context);
444 JSC::JSGlobalData* globalData = Heap::heap(str)->globalData();
446 // Check the normal world first!
447 JSGlobalData::ClientData* clientData = globalData->clientData;
449 JSStringCache& cache = static_cast<WebCoreJSClientData*>(clientData)->normalWorld()->m_stringCache;
450 if (cache.uncheckedRemove(cacheKey, str)) {
455 for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
456 if (worldIter->m_stringCache.uncheckedRemove(cacheKey, str))
463 JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl* stringImpl)
465 // If there is a stale entry, we have to explicitly remove it to avoid
466 // problems down the line.
467 if (JSString* wrapper = stringCache.uncheckedGet(stringImpl))
468 stringCache.uncheckedRemove(stringImpl, wrapper);
470 JSString* wrapper = jsStringWithFinalizer(exec, UString(stringImpl), stringWrapperDestroyed, stringImpl);
471 stringCache.set(stringImpl, wrapper);
472 // ref explicitly instead of using a RefPtr-keyed hashtable because the wrapper can
473 // outlive the cache, so the stringImpl has to match the wrapper's lifetime.
478 JSValue jsStringOrNull(ExecState* exec, const String& s)
482 return jsString(exec, s);
485 JSValue jsOwnedStringOrNull(ExecState* exec, const String& s)
489 return jsOwnedString(exec, stringToUString(s));
492 JSValue jsStringOrUndefined(ExecState* exec, const String& s)
495 return jsUndefined();
496 return jsString(exec, s);
499 JSValue jsStringOrFalse(ExecState* exec, const String& s)
502 return jsBoolean(false);
503 return jsString(exec, s);
506 JSValue jsString(ExecState* exec, const KURL& url)
508 return jsString(exec, url.string());
511 JSValue jsStringOrNull(ExecState* exec, const KURL& url)
515 return jsString(exec, url.string());
518 JSValue jsStringOrUndefined(ExecState* exec, const KURL& url)
521 return jsUndefined();
522 return jsString(exec, url.string());
525 JSValue jsStringOrFalse(ExecState* exec, const KURL& url)
528 return jsBoolean(false);
529 return jsString(exec, url.string());
532 AtomicStringImpl* findAtomicString(const Identifier& identifier)
534 if (identifier.isNull())
536 StringImpl* impl = identifier.impl();
537 ASSERT(impl->existingHash());
538 return AtomicString::find(impl->characters(), impl->length(), impl->existingHash());
541 String valueToStringWithNullCheck(ExecState* exec, JSValue value)
545 return ustringToString(value.toString(exec));
548 String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
550 if (value.isUndefinedOrNull())
552 return ustringToString(value.toString(exec));
555 JSValue jsDateOrNull(ExecState* exec, double value)
557 if (!isfinite(value))
559 return new (exec) DateInstance(exec, value);
562 double valueToDate(ExecState* exec, JSValue value)
564 if (value.isNumber())
565 return value.uncheckedGetNumber();
566 if (!value.inherits(&DateInstance::info))
567 return std::numeric_limits<double>::quiet_NaN();
568 return static_cast<DateInstance*>(value.toObject(exec))->internalNumber();
571 void reportException(ExecState* exec, JSValue exception)
573 if (exception.isObject() && asObject(exception)->exceptionType() == Terminated)
576 UString errorMessage = exception.toString(exec);
577 JSObject* exceptionObject = exception.toObject(exec);
578 int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec);
579 UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL")).toString(exec);
580 exec->clearException();
582 if (ExceptionBase* exceptionBase = toExceptionBase(exception))
583 errorMessage = stringToUString(exceptionBase->message() + ": " + exceptionBase->description());
585 ScriptExecutionContext* scriptExecutionContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();
586 ASSERT(scriptExecutionContext);
588 // Crash data indicates null-dereference crashes at this point in the Safari 4 Public Beta.
589 // It's harmless to return here without reporting the exception to the log and the debugger in this case.
590 if (!scriptExecutionContext)
593 scriptExecutionContext->reportException(ustringToString(errorMessage), lineNumber, ustringToString(exceptionSourceURL), 0);
596 void reportCurrentException(ExecState* exec)
598 JSValue exception = exec->exception();
599 exec->clearException();
600 reportException(exec, exception);
603 void setDOMException(ExecState* exec, ExceptionCode ec)
605 if (!ec || exec->hadException())
608 // FIXME: All callers to setDOMException need to pass in the right global object
609 // for now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this:
610 // frames[0].document.createElement(null, null); // throws an exception which should have the subframes prototypes.
611 JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec);
613 ExceptionCodeDescription description;
614 getExceptionCodeDescription(ec, description);
617 switch (description.type) {
618 case DOMExceptionType:
619 errorObject = toJS(exec, globalObject, DOMCoreException::create(description));
621 case RangeExceptionType:
622 errorObject = toJS(exec, globalObject, RangeException::create(description));
624 case EventExceptionType:
625 errorObject = toJS(exec, globalObject, EventException::create(description));
627 case XMLHttpRequestExceptionType:
628 errorObject = toJS(exec, globalObject, XMLHttpRequestException::create(description));
631 case SVGExceptionType:
632 errorObject = toJS(exec, globalObject, SVGException::create(description).get());
636 case XPathExceptionType:
637 errorObject = toJS(exec, globalObject, XPathException::create(description));
641 case SQLExceptionType:
642 errorObject = toJS(exec, globalObject, SQLException::create(description));
645 #if ENABLE(BLOB) || ENABLE(FILE_SYSTEM)
646 case FileExceptionType:
647 errorObject = toJS(exec, globalObject, FileException::create(description));
650 #if ENABLE(INDEXED_DATABASE)
651 case IDBDatabaseExceptionType:
652 errorObject = toJS(exec, globalObject, IDBDatabaseException::create(description));
658 throwError(exec, errorObject);
661 DOMWindow* activeDOMWindow(ExecState* exec)
663 return asJSDOMWindow(exec->lexicalGlobalObject())->impl();
666 DOMWindow* firstDOMWindow(ExecState* exec)
668 return asJSDOMWindow(exec->dynamicGlobalObject())->impl();
671 bool checkNodeSecurity(ExecState* exec, Node* node)
673 return node && allowsAccessFromFrame(exec, node->document()->frame());
676 bool allowsAccessFromFrame(ExecState* exec, Frame* frame)
680 JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec));
681 return window && window->allowsAccessFrom(exec);
684 bool allowsAccessFromFrame(ExecState* exec, Frame* frame, String& message)
688 JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec));
689 return window && window->allowsAccessFrom(exec, message);
692 void printErrorMessageForFrame(Frame* frame, const String& message)
696 frame->domWindow()->printErrorMessage(message);
699 // FIXME: We should remove or at least deprecate this function. Callers can use firstDOMWindow directly.
700 Frame* toDynamicFrame(ExecState* exec)
702 return firstDOMWindow(exec)->frame();
705 // FIXME: We should remove this function. Callers can use ScriptController directly.
706 bool processingUserGesture()
708 return ScriptController::processingUserGesture();
711 JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
713 return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, objectProtoFuncToString);
716 Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo)
718 JSDOMStructureMap& structures = globalObject->structures();
719 return structures.get(classInfo).get();
722 Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const ClassInfo* classInfo)
724 JSDOMStructureMap& structures = globalObject->structures();
725 ASSERT(!structures.contains(classInfo));
726 return structures.set(classInfo, structure).first->second.get();
729 JSC::JSObject* toJSSequence(ExecState* exec, JSValue value, unsigned& length)
731 JSObject* object = value.getObject();
733 throwTypeError(exec);
736 JSValue lengthValue = object->get(exec, exec->propertyNames().length);
737 if (exec->hadException())
740 if (lengthValue.isUndefinedOrNull()) {
741 throwTypeError(exec);
745 length = lengthValue.toUInt32(exec);
746 if (exec->hadException())
752 } // namespace WebCore