JSValue* jsNodePrototypeFunctionAppendChild(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { if (!thisValue->isObject(&JSNode::s_info)) return throwError(exec, TypeError); JSNode* castedThisObj = static_cast<JSNode*>(thisValue); return castedThisObj->appendChild(exec, args); }
void JSNodeOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) { JSNode* jsNode = jsCast<JSNode*>(handle.get().asCell()); DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context); uncacheWrapper(world, jsNode->impl(), jsNode); jsNode->releaseImpl(); }
void markDOMNodesForDocument(Document* doc) { // If a node's JS wrapper holds custom properties, those properties must // persist every time the node is fetched from the DOM. So, we keep JS // wrappers like that from being garbage collected. JSWrapperCache& nodeDict = doc->wrapperCache(); JSWrapperCache::iterator nodeEnd = nodeDict.end(); for (JSWrapperCache::iterator nodeIt = nodeDict.begin(); nodeIt != nodeEnd; ++nodeIt) { JSNode* jsNode = nodeIt->second; Node* node = jsNode->impl(); if (jsNode->marked()) continue; // No need to preserve a wrapper that has no custom properties or is no // longer fetchable through the DOM. if (!jsNode->hasCustomProperties() || !node->inDocument()) { //... unless the wrapper wraps a loading image, since the "new Image" // syntax allows an orphan image wrapper to be the last reference // to a loading image, whose load event might have important side-effects. if (!node->hasTagName(imgTag) || static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent()) continue; } jsNode->mark(); } }
JSValue* jsNodePrototypeFunctionNormalize(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { if (!thisValue->isObject(&JSNode::s_info)) return throwError(exec, TypeError); JSNode* castedThisObj = static_cast<JSNode*>(thisValue); Node* imp = static_cast<Node*>(castedThisObj->impl()); imp->normalize(); return jsUndefined(); }
void markDOMNodesForDocument(Document* doc) { JSWrapperCache& nodeDict = doc->wrapperCache(); JSWrapperCache::iterator nodeEnd = nodeDict.end(); for (JSWrapperCache::iterator nodeIt = nodeDict.begin(); nodeIt != nodeEnd; ++nodeIt) { JSNode* jsNode = nodeIt->second; if (!jsNode->marked() && isObservableThroughDOM(jsNode)) jsNode->mark(); } }
JSValue* jsNodePrototypeFunctionHasAttributes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { if (!thisValue->isObject(&JSNode::s_info)) return throwError(exec, TypeError); JSNode* castedThisObj = static_cast<JSNode*>(thisValue); Node* imp = static_cast<Node*>(castedThisObj->impl()); KJS::JSValue* result = jsBoolean(imp->hasAttributes()); return result; }
JSValue JSXSLTProcessor::importStylesheet(ExecState* exec) { JSValue nodeVal = exec->argument(0); if (nodeVal.inherits(&JSNode::s_info)) { JSNode* node = static_cast<JSNode*>(asObject(nodeVal)); impl()->importStylesheet(node->impl()); return jsUndefined(); } // Throw exception? return jsUndefined(); }
void JSNode::mark() { ASSERT(!marked()); Node* node = m_impl.get(); // Nodes in the document are kept alive by JSDocument::mark, // so we have no special responsibilities and can just call the base class here. if (node->inDocument()) { // But if the document isn't marked we have to mark it to ensure that // nodes reachable from this one are also marked if (Document* doc = node->ownerDocument()) if (DOMObject* docWrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), doc)) if (!docWrapper->marked()) docWrapper->mark(); DOMObject::mark(); return; } // This is a node outside the document, so find the root of the tree it is in, // and start marking from there. Node* root = node; for (Node* current = m_impl.get(); current; current = current->parentNode()) root = current; // If we're already marking this tree, then we can simply mark this wrapper // by calling the base class; our caller is iterating the tree. if (root->inSubtreeMark()) { DOMObject::mark(); return; } // Mark the whole tree; use the global set of roots to avoid reentering. root->setInSubtreeMark(true); for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) { JSNode* wrapper = getCachedDOMNodeWrapper(m_impl->document(), nodeToMark); if (wrapper) { if (!wrapper->marked()) wrapper->mark(); } else if (nodeToMark == node) { // This is the case where the map from the document to wrappers has // been cleared out, but a wrapper is being marked. For now, we'll // let the rest of the tree of wrappers get collected, because we have // no good way of finding them. Later we should test behavior of other // browsers and see if we need to preserve other wrappers in this case. if (!marked()) mark(); } } root->setInSubtreeMark(false); // Double check that we actually ended up marked. This assert caught problems in the past. ASSERT(marked()); }
JSValue* jsNodePrototypeFunctionLookupNamespaceURI(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { if (!thisValue->isObject(&JSNode::s_info)) return throwError(exec, TypeError); JSNode* castedThisObj = static_cast<JSNode*>(thisValue); Node* imp = static_cast<Node*>(castedThisObj->impl()); const UString& prefix = valueToStringWithNullCheck(exec, args[0]); KJS::JSValue* result = jsStringOrNull(exec, imp->lookupNamespaceURI(prefix)); return result; }
JSValue* jsNodePrototypeFunctionIsDefaultNamespace(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { if (!thisValue->isObject(&JSNode::s_info)) return throwError(exec, TypeError); JSNode* castedThisObj = static_cast<JSNode*>(thisValue); Node* imp = static_cast<Node*>(castedThisObj->impl()); const UString& namespaceURI = valueToStringWithNullCheck(exec, args[0]); KJS::JSValue* result = jsBoolean(imp->isDefaultNamespace(namespaceURI)); return result; }
JSValue* jsNodePrototypeFunctionCloneNode(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { if (!thisValue->isObject(&JSNode::s_info)) return throwError(exec, TypeError); JSNode* castedThisObj = static_cast<JSNode*>(thisValue); Node* imp = static_cast<Node*>(castedThisObj->impl()); bool deep = args[0]->toBoolean(exec); KJS::JSValue* result = toJS(exec, WTF::getPtr(imp->cloneNode(deep))); return result; }
JSValue* jsNodePrototypeFunctionIsSupported(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { if (!thisValue->isObject(&JSNode::s_info)) return throwError(exec, TypeError); JSNode* castedThisObj = static_cast<JSNode*>(thisValue); Node* imp = static_cast<Node*>(castedThisObj->impl()); const UString& feature = args[0]->toString(exec); const UString& version = valueToStringWithNullCheck(exec, args[1]); KJS::JSValue* result = jsBoolean(imp->isSupported(feature, version)); return result; }
void JSNode::visitChildren(JSCell* cell, SlotVisitor& visitor) { JSNode* thisObject = jsCast<JSNode*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); Base::visitChildren(thisObject, visitor); Node* node = thisObject->impl(); node->visitJSEventListeners(visitor); visitor.addOpaqueRoot(root(node)); }
JSValue JSXSLTProcessor::transformToDocument(ExecState* exec) { JSValue nodeVal = exec->argument(0); if (nodeVal.inherits(&JSNode::s_info)) { JSNode* node = static_cast<JSNode*>(asObject(nodeVal)); RefPtr<Document> resultDocument = impl()->transformToDocument(node->impl()); if (resultDocument) return toJS(exec, globalObject(), resultDocument.get()); return jsUndefined(); } // Throw exception? return jsUndefined(); }
bool JSNodeOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) { JSNode* jsNode = jsCast<JSNode*>(handle.get().asCell()); return isReachableFromDOM(jsNode, jsNode->impl(), visitor); }
bool JSNodeOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) { JSNode* jsNode = jsCast<JSNode*>(handle.slot()->asCell()); return isReachableFromDOM(&jsNode->wrapped(), visitor); }