void WebNodeCollection::assign(const WebNodeCollection& other) { HTMLCollection* p = const_cast<HTMLCollection*>(other.m_private); if (p) p->ref(); assign(p); }
v8::Handle<v8::Value> V8HTMLCollection::callAsFunctionCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLCollection.callAsFunction()"); if (args.Length() < 1) return v8::Undefined(); HTMLCollection* imp = V8HTMLCollection::toNative(args.Holder()); if (args.Length() == 1) return getItem(imp, args[0]); // If there is a second argument it is the index of the item we want. String name = toWebCoreString(args[0]); v8::Local<v8::Uint32> index = args[1]->ToArrayIndex(); if (index.IsEmpty()) return v8::Undefined(); unsigned current = index->Uint32Value(); Node* node = imp->namedItem(name); while (node) { if (!current) return toV8(node); node = imp->nextNamedItem(name); current--; } return v8::Undefined(); }
JSValue jsHTMLCollectionLength(ExecState* exec, JSValue slotBase, const Identifier&) { JSHTMLCollection* castedThis = static_cast<JSHTMLCollection*>(asObject(slotBase)); UNUSED_PARAM(exec); HTMLCollection* imp = static_cast<HTMLCollection*>(castedThis->impl()); JSValue result = jsNumber(imp->length()); return result; }
JSValue JSHTMLCollection::nameGetter(ExecState* exec, JSValue slotBase, PropertyName propertyName) { JSHTMLCollection* collection = jsCast<JSHTMLCollection*>(asObject(slotBase)); const AtomicString& name = propertyNameToAtomicString(propertyName); HTMLCollection* impl = collection->impl(); #if ENABLE(MICRODATA) if (impl->type() == ItemProperties) return toJS(exec, collection->globalObject(), static_cast<HTMLPropertiesCollection*>(impl)->propertyNodeList(name)); #endif return toJS(exec, collection->globalObject(), impl->namedItem(name)); }
JSValue JSC_HOST_CALL jsHTMLCollectionPrototypeFunctionTags(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UNUSED_PARAM(args); if (!thisValue.isObject(&JSHTMLCollection::s_info)) return throwError(exec, TypeError); JSHTMLCollection* castedThisObj = static_cast<JSHTMLCollection*>(asObject(thisValue)); HTMLCollection* imp = static_cast<HTMLCollection*>(castedThisObj->impl()); const UString& name = args.at(0).toString(exec); JSC::JSValue result = toJS(exec, WTF::getPtr(imp->tags(name))); return result; }
void WebDocument::forms(WebVector<WebFormElement>& results) const { HTMLCollection* forms = const_cast<Document*>(constUnwrap<Document>())->forms(); size_t sourceLength = forms->length(); Vector<WebFormElement> temp; temp.reserveCapacity(sourceLength); for (size_t i = 0; i < sourceLength; ++i) { Element* element = forms->item(i); // Strange but true, sometimes node can be 0. if (element && element->isHTMLElement()) temp.append(WebFormElement(toHTMLFormElement(element))); } results.assign(temp); }
HTMLImageElement* HTMLMapElement::imageElement() { HTMLCollection* images = document()->images(); for (unsigned i = 0; Node* curr = images->item(i); i++) { if (!curr->hasTagName(imgTag)) continue; // The HTMLImageElement's useMap() value includes the '#' symbol at the beginning, // which has to be stripped off. HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(curr); String useMapName = imageElement->getAttribute(usemapAttr).string().substring(1); if (equalIgnoringCase(useMapName, m_name)) return imageElement; } return 0; }
HTMLElement* HTMLTableRowElement::insertCell(int index, ExceptionState& exceptionState) { HTMLCollection* children = cells(); int numCells = children ? children->length() : 0; if (index < -1 || index > numCells) { exceptionState.throwDOMException( IndexSizeError, "The value provided (" + String::number(index) + ") is outside the range [-1, " + String::number(numCells) + "]."); return nullptr; } HTMLTableCellElement* cell = HTMLTableCellElement::create(tdTag, document()); if (numCells == index || index == -1) appendChild(cell, exceptionState); else insertBefore(cell, children->item(index), exceptionState); return cell; }
inline bool isMatchingElement(const HTMLCollection& htmlCollection, Element& element) { CollectionType type = htmlCollection.type(); if (!element.isHTMLElement() && !(type == DocAll || type == NodeChildren || type == WindowNamedItems)) return false; switch (type) { case DocImages: return element.hasTagName(imgTag); case DocScripts: return element.hasTagName(scriptTag); case DocForms: return element.hasTagName(formTag); case TableTBodies: return element.hasTagName(tbodyTag); case TRCells: return element.hasTagName(tdTag) || element.hasTagName(thTag); case TSectionRows: return element.hasTagName(trTag); case SelectOptions: return element.hasTagName(optionTag); case SelectedOptions: return element.hasTagName(optionTag) && toHTMLOptionElement(element).selected(); case DataListOptions: if (element.hasTagName(optionTag)) { HTMLOptionElement& option = toHTMLOptionElement(element); if (!option.isDisabledFormControl() && !option.value().isEmpty()) return true; } return false; case MapAreas: return element.hasTagName(areaTag); case DocApplets: return element.hasTagName(appletTag) || (element.hasTagName(objectTag) && toHTMLObjectElement(element).containsJavaApplet()); case DocEmbeds: return element.hasTagName(embedTag); case DocLinks: return (element.hasTagName(aTag) || element.hasTagName(areaTag)) && element.fastHasAttribute(hrefAttr); case DocAnchors: return element.hasTagName(aTag) && element.fastHasAttribute(nameAttr); case DocAll: case NodeChildren: return true; case DocumentNamedItems: return static_cast<const DocumentNameCollection&>(htmlCollection).nodeMatches(&element); case WindowNamedItems: return static_cast<const WindowNameCollection&>(htmlCollection).nodeMatches(&element); case FormControls: case TableRows: break; } ASSERT_NOT_REACHED(); return false; }
// HTMLCollections are strange objects, they support both get and call, // so that document.forms.item(0) and document.forms(0) both work. static EncodedJSValue JSC_HOST_CALL callHTMLCollection(ExecState* exec) { if (exec->argumentCount() < 1) return JSValue::encode(jsUndefined()); // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case. JSHTMLCollection* jsCollection = static_cast<JSHTMLCollection*>(exec->callee()); HTMLCollection* collection = jsCollection->impl(); // Also, do we need the TypeError test here ? if (exec->argumentCount() == 1) { // Support for document.all(<index>) etc. bool ok; UString string = exec->argument(0).toString(exec); unsigned index = Identifier::toUInt32(string, ok); if (ok) return JSValue::encode(toJS(exec, jsCollection->globalObject(), collection->item(index))); // Support for document.images('<name>') etc. return JSValue::encode(getNamedItems(exec, jsCollection, Identifier(exec, string))); } // The second arg, if set, is the index of the item we want bool ok; UString string = exec->argument(0).toString(exec); unsigned index = Identifier::toUInt32(exec->argument(1).toString(exec), ok); if (ok) { String pstr = ustringToString(string); Node* node = collection->namedItem(pstr); while (node) { if (!index) return JSValue::encode(toJS(exec, jsCollection->globalObject(), node)); node = collection->nextNamedItem(pstr); --index; } } return JSValue::encode(jsUndefined()); }
// HTMLCollections are strange objects, they support both get and call, // so that document.forms.item(0) and document.forms(0) both work. static JSValue JSC_HOST_CALL callHTMLCollection(ExecState* exec, JSObject* function, JSValue, const ArgList& args) { if (args.size() < 1) return jsUndefined(); // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case. JSHTMLCollection* jsCollection = static_cast<JSHTMLCollection*>(function); HTMLCollection* collection = jsCollection->impl(); // Also, do we need the TypeError test here ? if (args.size() == 1) { // Support for document.all(<index>) etc. bool ok; UString string = args.at(0).toString(exec); unsigned index = string.toUInt32(&ok, false); if (ok) return toJS(exec, jsCollection->globalObject(), collection->item(index)); // Support for document.images('<name>') etc. return getNamedItems(exec, jsCollection, Identifier(exec, string)); } // The second arg, if set, is the index of the item we want bool ok; UString string = args.at(0).toString(exec); unsigned index = args.at(1).toString(exec).toUInt32(&ok, false); if (ok) { String pstr = string; Node* node = collection->namedItem(pstr); while (node) { if (!index) return toJS(exec, jsCollection->globalObject(), node); node = collection->nextNamedItem(pstr); --index; } } return jsUndefined(); }
v8::Handle<v8::Value> V8HTMLCollection::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty()) return v8Undefined(); if (info.Holder()->HasRealNamedCallbackProperty(name)) return v8Undefined(); HTMLCollection* imp = V8HTMLCollection::toNative(info.Holder()); #if ENABLE(MICRODATA) if (imp->type() == ItemProperties) { if (!static_cast<HTMLPropertiesCollection*>(imp)->hasNamedItem(toWebCoreAtomicString(name))) return v8Undefined(); RefPtr<PropertyNodeList> item = static_cast<HTMLPropertiesCollection*>(imp)->propertyNodeList(toWebCoreAtomicString(name)); if (!item) return v8Undefined(); return toV8(item.release(), info.Holder(), info.GetIsolate()); } #endif Node* item = imp->namedItem(toWebCoreAtomicString(name)); if (!item) return v8Undefined(); return toV8(item, info.Holder(), info.GetIsolate()); }
static inline bool isMatchingHTMLElement(const HTMLCollection& htmlCollection, const HTMLElement& element) { switch (htmlCollection.type()) { case DocImages: return element.hasTagName(imgTag); case DocScripts: return element.hasTagName(scriptTag); case DocForms: return element.hasTagName(formTag); case DocumentNamedItems: return toDocumentNameCollection(htmlCollection).elementMatches(element); case TableTBodies: return element.hasTagName(tbodyTag); case TRCells: return element.hasTagName(tdTag) || element.hasTagName(thTag); case TSectionRows: return element.hasTagName(trTag); case SelectOptions: return toHTMLOptionsCollection(htmlCollection).elementMatches(element); case SelectedOptions: return isHTMLOptionElement(element) && toHTMLOptionElement(element).selected(); case DataListOptions: return toHTMLDataListOptionsCollection(htmlCollection).elementMatches(element); case MapAreas: return element.hasTagName(areaTag); case DocApplets: return isHTMLObjectElement(element) && toHTMLObjectElement(element).containsJavaApplet(); case DocEmbeds: return element.hasTagName(embedTag); case DocLinks: return (element.hasTagName(aTag) || element.hasTagName(areaTag)) && element.fastHasAttribute(hrefAttr); case DocAnchors: return element.hasTagName(aTag) && element.fastHasAttribute(nameAttr); case ClassCollectionType: case TagCollectionType: case HTMLTagCollectionType: case DocAll: case NodeChildren: case FormControls: case TableRows: case WindowNamedItems: case NameNodeListType: case RadioNodeListType: case RadioImgNodeListType: case LabelsNodeListType: ASSERT_NOT_REACHED(); } return false; }
void HTMLTableRowElement::deleteCell(int index, ExceptionState& exceptionState) { HTMLCollection* children = cells(); int numCells = children ? children->length() : 0; // 1. If index is less than −1 or greater than or equal to the number of // elements in the cells collection, then throw "IndexSizeError". if (index < -1 || index >= numCells) { exceptionState.throwDOMException( IndexSizeError, "The value provided (" + String::number(index) + ") is outside the range [0, " + String::number(numCells) + ")."); return; } // 2. If index is −1, remove the last element in the cells collection // from its parent, or do nothing if the cells collection is empty. if (index == -1) { if (numCells == 0) return; index = numCells - 1; } // 3. Remove the indexth element in the cells collection from its parent. Element* cell = children->item(index); HTMLElement::removeChild(cell, exceptionState); }
template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element) { CollectionType type = htmlCollection.type(); // These collections apply to any kind of Elements, not just HTMLElements. switch (type) { case DocAll: case NodeChildren: return true; case ClassCollectionType: return static_cast<const ClassCollection&>(htmlCollection).elementMatches(element); case TagCollectionType: return static_cast<const TagCollection&>(htmlCollection).elementMatches(element); case HTMLTagCollectionType: return static_cast<const HTMLTagCollection&>(htmlCollection).elementMatches(element); default: break; } // The following only applies to HTMLElements. if (!element.isHTMLElement()) return false; switch (type) { case DocImages: return element.hasLocalName(imgTag); case DocScripts: return element.hasLocalName(scriptTag); case DocForms: return element.hasLocalName(formTag); case TableTBodies: return element.hasLocalName(tbodyTag); case TRCells: return element.hasLocalName(tdTag) || element.hasLocalName(thTag); case TSectionRows: return element.hasLocalName(trTag); case SelectOptions: return element.hasLocalName(optionTag); case SelectedOptions: return element.hasLocalName(optionTag) && toHTMLOptionElement(element).selected(); case DataListOptions: if (element.hasLocalName(optionTag)) { const HTMLOptionElement& option = toHTMLOptionElement(element); if (!option.isDisabledFormControl() && !option.value().isEmpty()) return true; } return false; case MapAreas: return element.hasLocalName(areaTag); case DocApplets: return element.hasLocalName(appletTag) || (element.hasLocalName(objectTag) && toHTMLObjectElement(element).containsJavaApplet()); case DocEmbeds: return element.hasLocalName(embedTag); case DocLinks: return (element.hasLocalName(aTag) || element.hasLocalName(areaTag)) && element.fastHasAttribute(hrefAttr); case DocAnchors: return element.hasLocalName(aTag) && element.fastHasAttribute(nameAttr); case ClassCollectionType: case TagCollectionType: case HTMLTagCollectionType: case DocAll: case NodeChildren: case FormControls: case DocumentNamedItems: case TableRows: case WindowNamedItems: case NameNodeListType: case RadioNodeListType: case RadioImgNodeListType: case LabelsNodeListType: ASSERT_NOT_REACHED(); } return false; }
static v8::Handle<v8::Value> lengthAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLCollection.length._get"); HTMLCollection* imp = V8HTMLCollection::toNative(info.Holder()); return v8::Integer::NewFromUnsigned(imp->length()); }
void V8Window::namedPropertyGetterCustom( const AtomicString& name, const v8::PropertyCallbackInfo<v8::Value>& info) { DOMWindow* window = V8Window::toImpl(info.Holder()); if (!window) return; Frame* frame = window->frame(); // window is detached from a frame. if (!frame) return; // Note that the spec doesn't allow any cross-origin named access to the // window object. However, UAs have traditionally allowed named access to // named child browsing contexts, even across origins. So first, search child // frames for a frame with a matching name. Frame* child = frame->tree().scopedChild(name); if (child) { v8SetReturnValueFast(info, child->domWindow(), window); return; } // If the frame is remote, the caller will never be able to access further // named results. if (!frame->isLocalFrame()) return; // Search named items in the document. Document* doc = toLocalFrame(frame)->document(); if (!doc || !doc->isHTMLDocument()) return; // This is an AllCanRead interceptor. Check that the caller has access to the // named results. if (!BindingSecurity::shouldAllowAccessTo( currentDOMWindow(info.GetIsolate()), window, BindingSecurity::ErrorReportOption::DoNotReport)) return; bool hasNamedItem = toHTMLDocument(doc)->hasNamedItem(name); bool hasIdItem = doc->hasElementWithId(name); if (!hasNamedItem && !hasIdItem) return; if (!hasNamedItem && hasIdItem && !doc->containsMultipleElementsWithId(name)) { v8SetReturnValueFast(info, doc->getElementById(name), window); return; } HTMLCollection* items = doc->windowNamedItems(name); if (!items->isEmpty()) { // TODO(esprehn): Firefox doesn't return an HTMLCollection here if there's // multiple with the same name, but Chrome and Safari does. What's the // right behavior? if (items->hasExactlyOneItem()) { v8SetReturnValueFast(info, items->item(0), window); return; } v8SetReturnValueFast(info, items, window); return; } }