void PageSerializer::serializeFrame(Frame* frame) { Document* document = frame->document(); URL url = document->url(); if (!url.isValid() || url.isBlankURL()) { // For blank frames we generate a fake URL so they can be referenced by their containing frame. url = urlForBlankFrame(frame); } if (m_resourceURLs.contains(url)) { // FIXME: We could have 2 frame with the same URL but which were dynamically changed and have now // different content. So we should serialize both and somehow rename the frame src in the containing // frame. Arg! return; } Vector<Node*> nodes; SerializerMarkupAccumulator accumulator(*this, *document, &nodes); TextEncoding textEncoding(document->charset()); CString data; if (!textEncoding.isValid()) { // FIXME: iframes used as images trigger this. We should deal with them correctly. return; } String text = accumulator.serializeNodes(*document->documentElement(), 0, IncludeNode); CString frameHTML = textEncoding.encode(text, EntitiesForUnencodables); m_resources->append(Resource(url, document->suggestedMIMEType(), SharedBuffer::create(frameHTML.data(), frameHTML.length()))); m_resourceURLs.add(url); for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) { Node* node = *iter; if (!node->isElementNode()) continue; Element* element = toElement(node); // We have to process in-line style as it might contain some resources (typically background images). if (element->isStyledElement()) retrieveResourcesForProperties(toStyledElement(element)->inlineStyle(), document); if (isHTMLImageElement(element)) { HTMLImageElement* imageElement = toHTMLImageElement(element); URL url = document->completeURL(imageElement->getAttribute(HTMLNames::srcAttr)); CachedImage* cachedImage = imageElement->cachedImage(); addImageToResources(cachedImage, imageElement->renderer(), url); } else if (element->hasTagName(HTMLNames::linkTag)) { HTMLLinkElement* linkElement = toHTMLLinkElement(element); if (CSSStyleSheet* sheet = linkElement->sheet()) { URL url = document->completeURL(linkElement->getAttribute(HTMLNames::hrefAttr)); serializeCSSStyleSheet(sheet, url); ASSERT(m_resourceURLs.contains(url)); } } else if (isHTMLStyleElement(element)) { if (CSSStyleSheet* sheet = toHTMLStyleElement(element)->sheet()) serializeCSSStyleSheet(sheet, URL()); } } for (Frame* childFrame = frame->tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling()) serializeFrame(childFrame); }
ImportLoader* ImportManager::GetNearestPredecessor(nsINode* aNode) { // Return the previous link if there is any in the same document. nsIDocument* doc = aNode->OwnerDoc(); int32_t idx = doc->IndexOfSubImportLink(aNode); MOZ_ASSERT(idx != -1, "aNode must be a sub import link of its owner document"); for (; idx > 0; idx--) { HTMLLinkElement* link = static_cast<HTMLLinkElement*>(doc->GetSubImportLink(idx - 1)); nsCOMPtr<nsIURI> uri = link->GetHrefURI(); RefPtr<ImportLoader> ret; mImports.Get(uri, getter_AddRefs(ret)); // Only main referrer links are interesting. if (ret->GetMainReferrer() == link) { return ret; } } if (idx == 0) { if (doc->IsMasterDocument()) { // If there is no previous one, and it was the master document, then // there is no predecessor. return nullptr; } // Else we find the main referrer of the import parent of the link's document. // And do a recursion. ImportLoader* owner = Find(doc); MOZ_ASSERT(owner); nsCOMPtr<nsINode> mainReferrer = owner->GetMainReferrer(); return GetNearestPredecessor(mainReferrer); } return nullptr; }
WebURL WebDocument::manifestURL() const { const Document* document = constUnwrap<Document>(); HTMLLinkElement* linkElement = document->linkManifest(); if (!linkElement) return WebURL(); return linkElement->href(); }
ImportLoader* ImportManager::Find(nsINode* aLink) { HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(aLink); nsCOMPtr<nsIURI> uri = linkElement->GetHrefURI(); return mImports.GetWeak(uri); }
bool WebDocument::manifestUseCredentials() const { const Document* document = constUnwrap<Document>(); HTMLLinkElement* linkElement = document->linkManifest(); if (!linkElement) return false; return equalIgnoringCase(linkElement->fastGetAttribute(HTMLNames::crossoriginAttr), "use-credentials"); }
JSValue jsHTMLLinkElementTarget(ExecState* exec, JSValue slotBase, const Identifier&) { JSHTMLLinkElement* castedThis = static_cast<JSHTMLLinkElement*>(asObject(slotBase)); UNUSED_PARAM(exec); HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(castedThis->impl()); JSValue result = jsString(exec, imp->target()); return result; }
JSValue jsHTMLLinkElementSheet(ExecState* exec, JSValue slotBase, const Identifier&) { JSHTMLLinkElement* castedThis = static_cast<JSHTMLLinkElement*>(asObject(slotBase)); UNUSED_PARAM(exec); HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(castedThis->impl()); JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->sheet())); return result; }
JSValue jsHTMLLinkElementDisabled(ExecState* exec, JSValue slotBase, const Identifier&) { JSHTMLLinkElement* castedThis = static_cast<JSHTMLLinkElement*>(asObject(slotBase)); UNUSED_PARAM(exec); HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(castedThis->impl()); JSValue result = jsBoolean(imp->disabled()); return result; }
JSValue jsHTMLLinkElementType(ExecState* exec, JSValue slotBase, const Identifier&) { JSHTMLLinkElement* castedThis = static_cast<JSHTMLLinkElement*>(asObject(slotBase)); UNUSED_PARAM(exec); HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(castedThis->impl()); JSValue result = jsString(exec, imp->getAttribute(WebCore::HTMLNames::typeAttr)); return result; }
TEST(HTMLLinkElementSizesAttributeTest, setSizesAttribute_updatesSizesPropertyValue) { Document* document = Document::create(); HTMLLinkElement* link = HTMLLinkElement::create(*document, /* createdByParser: */ false); DOMTokenList* sizes = link->sizes(); EXPECT_EQ(nullAtom, sizes->value()); link->setAttribute(HTMLNames::sizesAttr, "y x "); EXPECT_EQ("y x ", sizes->value()); }
PassRefPtr<IconFetcher> IconFetcher::create(Frame* frame, IconFetcherClient* client) { Document* document = frame->document(); HTMLHeadElement* head = document->head(); if (!head) return 0; Vector<IconLinkEntry> entries; for (Node* n = head; n; n = n->traverseNextNode()) { if (!n->hasTagName(linkTag)) continue; HTMLLinkElement* link = static_cast<HTMLLinkElement*>(n); if (!link->isIcon()) continue; parseIconLink(link, entries); } if (entries.isEmpty()) return 0; // Check if any of the entries have the same type as the native icon type. // FIXME: This should be way more sophisticated, and handle conversion // of multisize formats for example. for (unsigned i = 0; i < entries.size(); i++) { const IconLinkEntry& entry = entries[i]; if (entry.type() == NativeIconType) { RefPtr<IconFetcher> iconFetcher = adoptRef(new IconFetcher(frame, client)); iconFetcher->m_entries.append(entry); iconFetcher->loadEntry(); return iconFetcher.release(); } } return 0; }
TEST_F(WebDocumentTest, ManifestUseCredentials) { loadURL(std::string(kDefaultOrigin) + kManifestDummyFilePath); WebDocument webDoc = topWebDocument(); Document* document = topDocument(); HTMLLinkElement* linkManifest = document->linkManifest(); // No crossorigin attribute was set so credentials shouldn't be used. ASSERT_FALSE(linkManifest->fastHasAttribute(HTMLNames::crossoriginAttr)); ASSERT_FALSE(webDoc.manifestUseCredentials()); // Crossorigin set to a random string shouldn't trigger using credentials. linkManifest->setAttribute(HTMLNames::crossoriginAttr, "foobar"); ASSERT_FALSE(webDoc.manifestUseCredentials()); // Crossorigin set to 'anonymous' shouldn't trigger using credentials. linkManifest->setAttribute(HTMLNames::crossoriginAttr, "anonymous"); ASSERT_FALSE(webDoc.manifestUseCredentials()); // Crossorigin set to 'use-credentials' should trigger using credentials. linkManifest->setAttribute(HTMLNames::crossoriginAttr, "use-credentials"); ASSERT_TRUE(webDoc.manifestUseCredentials()); }
TEST_F(WebDocumentTest, ManifestURL) { loadURL(std::string(kDefaultOrigin) + kManifestDummyFilePath); WebDocument webDoc = topWebDocument(); Document* document = topDocument(); HTMLLinkElement* linkManifest = document->linkManifest(); // No href attribute was set. ASSERT_EQ(linkManifest->href(), static_cast<KURL>(webDoc.manifestURL())); // Set to some absolute url. linkManifest->setAttribute(HTMLNames::hrefAttr, "http://example.com/manifest.json"); ASSERT_EQ(linkManifest->href(), static_cast<KURL>(webDoc.manifestURL())); // Set to some relative url. linkManifest->setAttribute(HTMLNames::hrefAttr, "static/manifest.json"); ASSERT_EQ(linkManifest->href(), static_cast<KURL>(webDoc.manifestURL())); }
v8::Handle<v8::Value> V8HTMLLinkElement::sizesAttrGetterCustom(v8::Local<v8::String> name, const v8::AccessorInfo& info) { HTMLLinkElement* imp = V8HTMLLinkElement::toNative(info.Holder()); return toV8Fast(imp->sizes(), info, imp); }
void DocumentStyleSheetCollection::collectActiveStyleSheets(Vector<RefPtr<StyleSheet> >& sheets) { if (m_document->settings() && !m_document->settings()->authorAndUserStylesEnabled()) return; StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin(); StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end(); for (StyleSheetCandidateListHashSet::iterator it = begin; it != end; ++it) { Node* n = *it; StyleSheet* sheet = 0; if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) { // Processing instruction (XML documents only). // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion. ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n); sheet = pi->sheet(); #if ENABLE(XSLT) // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806> if (pi->isXSL() && !m_document->transformSourceDocument()) { // Don't apply XSL transforms until loading is finished. if (!m_document->parsing()) m_document->applyXSLTransform(pi); return; } #endif } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) #if ENABLE(SVG) || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) #endif ) { Element* e = toElement(n); AtomicString title = e->getAttribute(titleAttr); bool enabledViaScript = false; if (e->hasTagName(linkTag)) { // <LINK> element HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(n); if (linkElement->isDisabled()) continue; enabledViaScript = linkElement->isEnabledViaScript(); if (linkElement->styleSheetIsLoading()) { // it is loading but we should still decide which style sheet set to use if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSetName.isEmpty()) { const AtomicString& rel = e->getAttribute(relAttr); if (!rel.contains("alternate")) { m_preferredStylesheetSetName = title; m_selectedStylesheetSetName = title; } } continue; } if (!linkElement->sheet()) title = nullAtom; } // Get the current preferred styleset. This is the // set of sheets that will be enabled. #if ENABLE(SVG) if (e->hasTagName(SVGNames::styleTag)) sheet = static_cast<SVGStyleElement*>(n)->sheet(); else #endif { if (e->hasTagName(linkTag)) sheet = static_cast<HTMLLinkElement*>(n)->sheet(); else // <STYLE> element sheet = toHTMLStyleElement(e)->sheet(); } // Check to see if this sheet belongs to a styleset // (thus making it PREFERRED or ALTERNATE rather than // PERSISTENT). AtomicString rel = e->getAttribute(relAttr); if (!enabledViaScript && !title.isEmpty()) { // Yes, we have a title. if (m_preferredStylesheetSetName.isEmpty()) { // No preferred set has been established. If // we are NOT an alternate sheet, then establish // us as the preferred set. Otherwise, just ignore // this sheet. if (e->hasTagName(styleTag) || !rel.contains("alternate")) m_preferredStylesheetSetName = m_selectedStylesheetSetName = title; } if (title != m_preferredStylesheetSetName) sheet = 0; } if (rel.contains("alternate") && title.isEmpty()) sheet = 0; } if (sheet) sheets.append(sheet); } }
v8::Handle<v8::Value> V8HTMLLinkElement::sizesAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLLinkElement.sizes._get"); HTMLLinkElement* imp = V8HTMLLinkElement::toNative(info.Holder()); return toV8(imp->sizes()); }
void FrameLoaderClientBlackBerry::dispatchDidFinishLoad() { didFinishOrFailLoading(ResourceError()); if (m_webPagePrivate->m_dumpRenderTree) m_webPagePrivate->m_dumpRenderTree->didFinishLoadForFrame(m_frame); if (!isMainFrame() || m_webPagePrivate->m_webSettings->isEmailMode() || !m_frame->document() || !m_frame->document()->head()) return; HTMLHeadElement* headElement = m_frame->document()->head(); // FIXME: Handle NOSCRIPT special case? // Process document metadata. RefPtr<NodeList> nodeList = headElement->getElementsByTagName(HTMLNames::metaTag.localName()); unsigned int size = nodeList->length(); ScopeArray<WebString> headers; // This may allocate more space than needed since not all meta elements will be http-equiv. headers.reset(new WebString[2 * size]); unsigned headersLength = 0; for (unsigned i = 0; i < size; ++i) { HTMLMetaElement* metaElement = static_cast<HTMLMetaElement*>(nodeList->item(i)); if (WTF::equalIgnoringCase(metaElement->name(), "apple-mobile-web-app-capable") && WTF::equalIgnoringCase(metaElement->content().stripWhiteSpace(), "yes")) m_webPagePrivate->m_client->setWebAppCapable(); else { String httpEquiv = metaElement->httpEquiv().stripWhiteSpace(); String content = metaElement->content().stripWhiteSpace(); if (!httpEquiv.isNull() && !content.isNull()) { headers[headersLength++] = httpEquiv; headers[headersLength++] = content; } } } if (headersLength > 0) m_webPagePrivate->m_client->setMetaHeaders(headers, headersLength); nodeList = headElement->getElementsByTagName(HTMLNames::linkTag.localName()); size = nodeList->length(); for (unsigned i = 0; i < size; ++i) { HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(nodeList->item(i)); String href = linkElement->href().string(); if (!href.isEmpty()) { String title = linkElement->title(); if (WTF::equalIgnoringCase(linkElement->rel(), "apple-touch-icon")) m_webPagePrivate->m_client->setLargeIcon(href.latin1().data()); else if (WTF::equalIgnoringCase(linkElement->rel(), "search")) { if (WTF::equalIgnoringCase(linkElement->type(), "application/opensearchdescription+xml")) m_webPagePrivate->m_client->setSearchProviderDetails(title.utf8().data(), href.utf8().data()); } else if (WTF::equalIgnoringCase(linkElement->rel(), "alternate") && (WTF::equalIgnoringCase(linkElement->type(), "application/rss+xml") || WTF::equalIgnoringCase(linkElement->type(), "application/atom+xml"))) m_webPagePrivate->m_client->setAlternateFeedDetails(title.utf8().data(), href.utf8().data()); } } #if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST) if (!m_webPagePrivate->m_webSettings->isPrivateBrowsingEnabled()) credentialManager().autofillPasswordForms(m_frame->document()->forms()); #endif }
// This test checks that Documunt::linkManifest() returns a value conform to the specification. TEST_F(DocumentTest, LinkManifest) { // Test the default result. EXPECT_EQ(0, document().linkManifest()); // Check that we use the first manifest with <link rel=manifest> HTMLLinkElement* link = HTMLLinkElement::create(document(), false); link->setAttribute(blink::HTMLNames::relAttr, "manifest"); link->setAttribute(blink::HTMLNames::hrefAttr, "foo.json"); document().head()->appendChild(link); EXPECT_EQ(link, document().linkManifest()); HTMLLinkElement* link2 = HTMLLinkElement::create(document(), false); link2->setAttribute(blink::HTMLNames::relAttr, "manifest"); link2->setAttribute(blink::HTMLNames::hrefAttr, "bar.json"); document().head()->insertBefore(link2, link); EXPECT_EQ(link2, document().linkManifest()); document().head()->appendChild(link2); EXPECT_EQ(link, document().linkManifest()); // Check that crazy URLs are accepted. link->setAttribute(blink::HTMLNames::hrefAttr, "http:foo.json"); EXPECT_EQ(link, document().linkManifest()); // Check that empty URLs are accepted. link->setAttribute(blink::HTMLNames::hrefAttr, ""); EXPECT_EQ(link, document().linkManifest()); // Check that URLs from different origins are accepted. link->setAttribute(blink::HTMLNames::hrefAttr, "http://example.org/manifest.json"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::hrefAttr, "http://foo.example.org/manifest.json"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::hrefAttr, "http://foo.bar/manifest.json"); EXPECT_EQ(link, document().linkManifest()); // More than one token in @rel is accepted. link->setAttribute(blink::HTMLNames::relAttr, "foo bar manifest"); EXPECT_EQ(link, document().linkManifest()); // Such as spaces around the token. link->setAttribute(blink::HTMLNames::relAttr, " manifest "); EXPECT_EQ(link, document().linkManifest()); // Check that rel=manifest actually matters. link->setAttribute(blink::HTMLNames::relAttr, ""); EXPECT_EQ(link2, document().linkManifest()); link->setAttribute(blink::HTMLNames::relAttr, "manifest"); // Check that link outside of the <head> are ignored. document().head()->removeChild(link, ASSERT_NO_EXCEPTION); document().head()->removeChild(link2, ASSERT_NO_EXCEPTION); EXPECT_EQ(0, document().linkManifest()); document().body()->appendChild(link); EXPECT_EQ(0, document().linkManifest()); document().head()->appendChild(link); document().head()->appendChild(link2); // Check that some attribute values do not have an effect. link->setAttribute(blink::HTMLNames::crossoriginAttr, "use-credentials"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::hreflangAttr, "klingon"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::typeAttr, "image/gif"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::sizesAttr, "16x16"); EXPECT_EQ(link, document().linkManifest()); link->setAttribute(blink::HTMLNames::mediaAttr, "print"); EXPECT_EQ(link, document().linkManifest()); }
void setJSHTMLLinkElementType(ExecState* exec, JSObject* thisObject, JSValue value) { JSHTMLLinkElement* castedThis = static_cast<JSHTMLLinkElement*>(thisObject); HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(castedThis->impl()); imp->setAttribute(WebCore::HTMLNames::typeAttr, valueToStringWithNullCheck(exec, value)); }
void V8HTMLLinkElement::sizesAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLLinkElement.sizes._set"); HTMLLinkElement* imp = V8HTMLLinkElement::toNative(info.Holder()); imp->setSizes(toWebCoreString(value)); }
void setJSHTMLLinkElementDisabled(ExecState* exec, JSObject* thisObject, JSValue value) { JSHTMLLinkElement* castedThis = static_cast<JSHTMLLinkElement*>(thisObject); HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(castedThis->impl()); imp->setDisabled(value.toBoolean(exec)); }
void JSHTMLLinkElement::putValueProperty(ExecState* exec, int token, JSValue* value) { switch (token) { case DisabledAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setDisabled(value->toBoolean(exec)); break; } case CharsetAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setCharset(valueToStringWithNullCheck(exec, value)); break; } case HrefAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setHref(valueToStringWithNullCheck(exec, value)); break; } case HreflangAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setHreflang(valueToStringWithNullCheck(exec, value)); break; } case MediaAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setMedia(valueToStringWithNullCheck(exec, value)); break; } case RelAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setRel(valueToStringWithNullCheck(exec, value)); break; } case RevAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setRev(valueToStringWithNullCheck(exec, value)); break; } case TargetAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setTarget(valueToStringWithNullCheck(exec, value)); break; } case TypeAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); imp->setType(valueToStringWithNullCheck(exec, value)); break; } } }
void V8HTMLLinkElement::sizesAttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { HTMLLinkElement* imp = V8HTMLLinkElement::toNative(info.Holder()); imp->setSizes(toWebCoreString(value)); }
void setJSHTMLLinkElementType(ExecState* exec, JSObject* thisObject, JSValue value) { JSHTMLLinkElement* castedThisObj = static_cast<JSHTMLLinkElement*>(thisObject); HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(castedThisObj->impl()); imp->setType(valueToStringWithNullCheck(exec, value)); }
JSValue* JSHTMLLinkElement::getValueProperty(ExecState* exec, int token) const { switch (token) { case DisabledAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsBoolean(imp->disabled()); } case CharsetAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsString(exec, imp->charset()); } case HrefAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsString(exec, imp->href()); } case HreflangAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsString(exec, imp->hreflang()); } case MediaAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsString(exec, imp->media()); } case RelAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsString(exec, imp->rel()); } case RevAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsString(exec, imp->rev()); } case TargetAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsString(exec, imp->target()); } case TypeAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return jsString(exec, imp->type()); } case SheetAttrNum: { HTMLLinkElement* imp = static_cast<HTMLLinkElement*>(impl()); return toJS(exec, WTF::getPtr(imp->sheet())); } case ConstructorAttrNum: return getConstructor(exec); } return 0; }