diff --git a/khtml/ecma/kjs_html.cpp b/khtml/ecma/kjs_html.cpp index 4f3e54f4c2..1cc55e70e4 100644 --- a/khtml/ecma/kjs_html.cpp +++ b/khtml/ecma/kjs_html.cpp @@ -1,3426 +1,3426 @@ // -*- c-basic-offset: 2 -*- /* * This file is part of the KDE libraries * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001-2003 David Faure (faure@kde.org) * Copyright (C) 2004 Apple Computer, Inc. * Copyright (C) 2005 Maksim Orlovich (maksim@kde.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "kjs_html.h" #include "kjs_html.lut.h" #include #include #include #include #include #include #include #include #include #include // ### HACK #include #include #include #include #include #include #include #include #include "kjs_css.h" #include "kjs_events.h" #include "kjs_window.h" #include "kjs_context2d.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace KJS { KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLDocumentProto, DOMDocumentProto) KJS_IMPLEMENT_PROTOFUNC(HTMLDocFunction) KJS_IMPLEMENT_PROTOTYPE("HTMLDocument", HTMLDocumentProto, HTMLDocFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLDocumentPseudoCtor, "HTMLDocument", HTMLDocumentProto) /* Source for HTMLDocumentProtoTable. @begin HTMLDocumentProtoTable 11 clear HTMLDocument::Clear DontDelete|Function 0 open HTMLDocument::Open DontDelete|Function 0 close HTMLDocument::Close DontDelete|Function 0 write HTMLDocument::Write DontDelete|Function 1 writeln HTMLDocument::WriteLn DontDelete|Function 1 getElementsByName HTMLDocument::GetElementsByName DontDelete|Function 1 getSelection HTMLDocument::GetSelection DontDelete|Function 1 captureEvents HTMLDocument::CaptureEvents DontDelete|Function 0 releaseEvents HTMLDocument::ReleaseEvents DontDelete|Function 0 @end */ JSValue* KJS::HTMLDocFunction::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { KJS_CHECK_THIS( HTMLDocument, thisObj ); DOM::HTMLDocumentImpl& doc = *static_cast(thisObj)->impl(); switch (id) { case HTMLDocument::Clear: // even IE doesn't support that one... //doc.clear(); // TODO return jsUndefined(); case HTMLDocument::Open: if (args.size() >= 3) // IE extension for document.open: it means window.open if it has 3 args or more { KHTMLView *view = doc.view(); if ( view && view->part() ) { Window* win = Window::retrieveWindow(view->part()); if( win ) { win->openWindow(exec, args); } } } doc.open(); return jsUndefined(); case HTMLDocument::Close: // see khtmltests/ecma/tokenizer-script-recursion.html doc.close(); return jsUndefined(); case HTMLDocument::Write: case HTMLDocument::WriteLn: { // DOM only specifies single string argument, but NS & IE allow multiple // or no arguments UString str = ""; for (int i = 0; i < args.size(); i++) str += args[i]->toString(exec); if (id == HTMLDocument::WriteLn) str += "\n"; #ifdef KJS_VERBOSE kDebug(6070) << "document.write: " << str.qstring(); #endif doc.write(str.qstring()); return jsUndefined(); } case HTMLDocument::GetElementsByName: return getDOMNodeList(exec,doc.getElementsByName(args[0]->toString(exec).domString())); case HTMLDocument::GetSelection: { // NS4 and Mozilla specific. IE uses document.selection.createRange() // http://docs.sun.com/source/816-6408-10/document.htm#1195981 KHTMLView *view = doc.view(); if ( view && view->part() ) return jsString(view->part()->selectedText()); else return jsUndefined(); } case HTMLDocument::CaptureEvents: case HTMLDocument::ReleaseEvents: // Do nothing for now. These are NS-specific legacy calls. break; } return jsUndefined(); } const ClassInfo KJS::HTMLDocument::info = { "HTMLDocument", &DOMDocument::info, &HTMLDocumentTable, 0 }; /* Source for HTMLDocumentTable. @begin HTMLDocumentTable 31 title HTMLDocument::Title DontDelete referrer HTMLDocument::Referrer DontDelete|ReadOnly domain HTMLDocument::Domain DontDelete URL HTMLDocument::URL DontDelete|ReadOnly body HTMLDocument::Body DontDelete location HTMLDocument::Location DontDelete cookie HTMLDocument::Cookie DontDelete images HTMLDocument::Images DontDelete|ReadOnly applets HTMLDocument::Applets DontDelete|ReadOnly links HTMLDocument::Links DontDelete|ReadOnly forms HTMLDocument::Forms DontDelete|ReadOnly anchors HTMLDocument::Anchors DontDelete|ReadOnly scripts HTMLDocument::Scripts DontDelete|ReadOnly all HTMLDocument::All DontDelete|ReadOnly bgColor HTMLDocument::BgColor DontDelete fgColor HTMLDocument::FgColor DontDelete alinkColor HTMLDocument::AlinkColor DontDelete linkColor HTMLDocument::LinkColor DontDelete vlinkColor HTMLDocument::VlinkColor DontDelete lastModified HTMLDocument::LastModified DontDelete|ReadOnly height HTMLDocument::Height DontDelete|ReadOnly width HTMLDocument::Width DontDelete|ReadOnly dir HTMLDocument::Dir DontDelete compatMode HTMLDocument::CompatMode DontDelete|ReadOnly #IE extension frames HTMLDocument::Frames DontDelete|ReadOnly #NS4 extension layers HTMLDocument::Layers DontDelete|ReadOnly #potentially obsolete array properties # plugins # tags #potentially obsolete properties # embeds # ids @end */ KJS::HTMLDocument::HTMLDocument(ExecState *exec, DOM::HTMLDocumentImpl* d) : DOMDocument(HTMLDocumentProto::self(exec), d) { } /* Should this property be checked after overrides? */ static bool isLateProperty(unsigned token) { switch (token) { case HTMLDocument::BgColor: case HTMLDocument::FgColor: case HTMLDocument::AlinkColor: case HTMLDocument::LinkColor: case HTMLDocument::VlinkColor: case HTMLDocument::LastModified: case HTMLDocument::Height: // NS-only, not available in IE case HTMLDocument::Width: // NS-only, not available in IE case HTMLDocument::Dir: case HTMLDocument::Frames: return true; default: return false; } } bool KJS::HTMLDocument::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot& slot) { #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLDocument::getOwnPropertySlot " << propertyName.qstring(); #endif DOM::DocumentImpl* docImpl = impl(); KHTMLView *view = docImpl->view(); Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L; if ( !win || !win->isSafeScript(exec) ) { slot.setUndefined(this); return true; } QString propertyQString = propertyName.qstring(); //See whether to return named items under document. ElementMappingCache::ItemInfo* info = docImpl->underDocNamedCache().get(propertyQString); if (info) { //May be a false positive, but we can try to avoid doing it the hard way in //simpler cases. The trickiness here is that the cache is kept under both //name and id, but we sometimes ignore id for IE compat DOM::DOMString propertyDOMString = propertyName.domString(); bool matched = false; if (info->nd && DOM::HTMLMappedNameCollectionImpl::matchesName(info->nd, HTMLCollectionImpl::DOCUMENT_NAMED_ITEMS, propertyDOMString)) { matched = true; } else { //Can't tell it just like that, so better go through collection and count stuff. This is the slow path... DOM::HTMLMappedNameCollectionImpl coll(impl(), HTMLCollectionImpl::DOCUMENT_NAMED_ITEMS, propertyDOMString); matched = coll.firstItem() != 0; } if (matched) { slot.setCustom(this, nameGetter); return true; } } // Check for frames/iframes with name==propertyName if ( view && view->part() ) { if (view->part()->findFrame( propertyQString )) { slot.setCustom(this, frameNameGetter); return true; } } // Static properties const HashEntry* entry = Lookup::findEntry(&HTMLDocumentTable, propertyName); if (entry && !isLateProperty(entry->value)) { getSlotFromEntry(entry, this, slot); return true; } // Look for overrides JSValue **val = getDirectLocation(propertyName); if (val) { - slot.setValueSlot(this, val); + fillDirectLocationSlot(slot, val); return true; } // The rest of static properties -- the late ones. if (entry) { getSlotFromEntry(entry, this, slot); return true; } return DOMDocument::getOwnPropertySlot(exec, propertyName, slot); } JSValue *HTMLDocument::nameGetter(ExecState *exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot) { HTMLDocument *thisObj = static_cast(slot.slotBase()); DOM::DocumentImpl* docImpl = thisObj->impl(); //Return named items under document (e.g. images, applets, etc.) ElementMappingCache::ItemInfo* info = docImpl->underDocNamedCache().get(propertyName.qstring()); if (info && info->nd) return getDOMNode(exec, info->nd); else { //No cached mapping, do it the hard way.. DOM::HTMLMappedNameCollectionImpl* coll = new DOM::HTMLMappedNameCollectionImpl(docImpl, HTMLCollectionImpl::DOCUMENT_NAMED_ITEMS, propertyName.domString()); if (info && coll->length() == 1) { info->nd = static_cast(coll->firstItem()); delete coll; return getDOMNode(exec, info->nd); } return getHTMLCollection(exec, coll); } assert(0); return jsUndefined(); } JSValue *HTMLDocument::frameNameGetter(ExecState*, JSObject*, const Identifier& name, const PropertySlot& slot) { HTMLDocument *thisObj = static_cast(slot.slotBase()); KHTMLView *view = thisObj->impl()->view(); // Check for frames/iframes with name==propertyName return Window::retrieve(view->part()->findFrame( name.qstring() )); } JSValue *HTMLDocument::objectNameGetter(ExecState *exec, JSObject*, const Identifier& name, const PropertySlot& slot) { HTMLDocument *thisObj = static_cast(slot.slotBase()); DOM::HTMLCollectionImpl objectLike(thisObj->impl(), DOM::HTMLCollectionImpl::DOC_APPLETS); return getDOMNode(exec, objectLike.namedItem(name.domString())); } JSValue *HTMLDocument::layerNameGetter(ExecState *exec, JSObject*, const Identifier& name, const PropertySlot& slot) { HTMLDocument *thisObj = static_cast(slot.slotBase()); DOM::HTMLCollectionImpl layerLike(thisObj->impl(), DOM::HTMLCollectionImpl::DOC_LAYERS); return getDOMNode(exec, layerLike.namedItem(name.domString())); } JSValue* HTMLDocument::getValueProperty(ExecState *exec, int token) { DOM::HTMLDocumentImpl& doc = *impl(); KHTMLView *view = doc.view(); Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L; DOM::HTMLElementImpl* body = doc.body(); switch (token) { case Title: return jsString(doc.title()); case Referrer: return jsString(doc.referrer()); case Domain: return jsString(doc.domain()); case URL: return jsString(doc.URL().url()); case Body: return getDOMNode(exec,doc.body()); case Location: if (win) return win->location(); else return jsUndefined(); case Cookie: return jsString(doc.cookie()); case Images: return getHTMLCollection(exec,doc.images()); case Applets: return getHTMLCollection(exec,doc.applets()); case Links: return getHTMLCollection(exec,doc.links()); case Forms: return getHTMLCollection(exec,doc.forms()); case Layers: // ### Should not be hidden when we emulate Netscape4 return getHTMLCollection(exec,doc.layers(), true); case Anchors: return getHTMLCollection(exec,doc.anchors()); case Scripts: return getHTMLCollection(exec,doc.scripts()); case All: // Disable document.all when we try to be Netscape-compatible if ( exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat ) return jsUndefined(); else if ( exec->dynamicInterpreter()->compatMode() == Interpreter::IECompat ) return getHTMLCollection(exec,doc.all()); else // enabled but hidden return getHTMLCollection(exec,doc.all(), true); case CompatMode: return jsString(doc.parseMode() == DocumentImpl::Compat ? "BackCompat" : "CSS1Compat"); case BgColor: return jsString(body->getAttribute(ATTR_BGCOLOR)); case FgColor: return jsString(body->getAttribute(ATTR_TEXT)); case AlinkColor: return jsString(body->getAttribute(ATTR_ALINK)); case LinkColor: return jsString(body->getAttribute(ATTR_LINK)); case VlinkColor: return jsString(body->getAttribute(ATTR_VLINK)); case LastModified: return jsString(doc.lastModified()); case Height: // NS-only, not available in IE return jsNumber(view ? view->contentsHeight() : 0); case Width: // NS-only, not available in IE return jsNumber(view ? view->contentsWidth() : 0); case Dir: return jsString(body->getAttribute(ATTR_DIR)); case Frames: if ( win ) return win->frames(exec); else return jsUndefined(); } assert(0); return 0; } void KJS::HTMLDocument::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) { #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLDocument::out " << propertyName.qstring(); #endif KHTMLView *view = impl()->view(); Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L; if ( !win || !win->isSafeScript(exec) ) return; lookupPut( exec, propertyName, value, attr, &HTMLDocumentTable, this ); } void KJS::HTMLDocument::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/) { DOM::HTMLDocumentImpl& doc = *impl(); DOM::DOMString val = value->toString(exec).domString(); DOMExceptionTranslator exception(exec); switch (token) { case Title: if (doc.title() != val) doc.setTitle(val); return; case Body: { DOM::NodeImpl* body = toNode(value); if (body->isHTMLElement()) doc.setBody(static_cast(body), exception); return; } case Domain: { // not part of the DOM doc.setDomain(val); return; } case Cookie: doc.setCookie(val); return; case Location: { KHTMLView *view = doc.view(); if ( view ) Window::retrieveWindow(view->part())->goURL(exec, value->toString(exec).qstring(), false /*don't lock history*/); return; } } /* The rest of the properties require a body. Note that Doc::body may be the frameset(!!) so we have to be a bit careful here. I am not sure this is 100% right, but it should match previous behavior - M.O. */ DOM::HTMLElementImpl* bodyCand = doc.body(); if (!bodyCand || bodyCand->id() != ID_BODY) return; //Just ignore. DOM::HTMLBodyElementImpl& body = *static_cast(bodyCand); switch (token) { case BgColor: if (body.bgColor() != val) body.setBgColor(val); break; case FgColor: if (body.text() != val) body.setText(val); break; case AlinkColor: if (body.aLink() != val) body.setALink(val); break; case LinkColor: if (body.link() != val) body.setLink(val); break; case VlinkColor: if (body.vLink() != val) body.setVLink(val); break; case Dir: body.setAttribute(ID_DIR, value->toString(exec).domString()); break; default: kDebug(6070) << "WARNING: HTMLDocument::putValueProperty unhandled token " << token; } } // ------------------------------------------------------------------------- const ClassInfo KJS::HTMLElement::info = { "HTMLElement", &DOMElement::info, &HTMLElementTable, 0 }; const ClassInfo KJS::HTMLElement::html_info = { "HTMLHtmlElement", &KJS::HTMLElement::info, &HTMLHtmlElementTable, 0 }; const ClassInfo KJS::HTMLElement::head_info = { "HTMLHeadElement", &KJS::HTMLElement::info, &HTMLHeadElementTable, 0 }; const ClassInfo KJS::HTMLElement::link_info = { "HTMLLinkElement", &KJS::HTMLElement::info, &HTMLLinkElementTable, 0 }; const ClassInfo KJS::HTMLElement::title_info = { "HTMLTitleElement", &KJS::HTMLElement::info, &HTMLTitleElementTable, 0 }; const ClassInfo KJS::HTMLElement::meta_info = { "HTMLMetaElement", &KJS::HTMLElement::info, &HTMLMetaElementTable, 0 }; const ClassInfo KJS::HTMLElement::base_info = { "HTMLBaseElement", &KJS::HTMLElement::info, &HTMLBaseElementTable, 0 }; const ClassInfo KJS::HTMLElement::isIndex_info = { "HTMLIsIndexElement", &KJS::HTMLElement::info, &HTMLIsIndexElementTable, 0 }; const ClassInfo KJS::HTMLElement::style_info = { "HTMLStyleElement", &KJS::HTMLElement::info, &HTMLStyleElementTable, 0 }; const ClassInfo KJS::HTMLElement::body_info = { "HTMLBodyElement", &KJS::HTMLElement::info, &HTMLBodyElementTable, 0 }; const ClassInfo KJS::HTMLElement::form_info = { "HTMLFormElement", &KJS::HTMLElement::info, &HTMLFormElementTable, 0 }; const ClassInfo KJS::HTMLElement::select_info = { "HTMLSelectElement", &KJS::HTMLElement::info, &HTMLSelectElementTable, 0 }; const ClassInfo KJS::HTMLElement::optGroup_info = { "HTMLOptGroupElement", &KJS::HTMLElement::info, &HTMLOptGroupElementTable, 0 }; const ClassInfo KJS::HTMLElement::option_info = { "HTMLOptionElement", &KJS::HTMLElement::info, &HTMLOptionElementTable, 0 }; const ClassInfo KJS::HTMLElement::input_info = { "HTMLInputElement", &KJS::HTMLElement::info, &HTMLInputElementTable, 0 }; const ClassInfo KJS::HTMLElement::textArea_info = { "HTMLTextAreaElement", &KJS::HTMLElement::info, &HTMLTextAreaElementTable, 0 }; const ClassInfo KJS::HTMLElement::button_info = { "HTMLButtonElement", &KJS::HTMLElement::info, &HTMLButtonElementTable, 0 }; const ClassInfo KJS::HTMLElement::label_info = { "HTMLLabelElement", &KJS::HTMLElement::info, &HTMLLabelElementTable, 0 }; const ClassInfo KJS::HTMLElement::fieldSet_info = { "HTMLFieldSetElement", &KJS::HTMLElement::info, &HTMLFieldSetElementTable, 0 }; const ClassInfo KJS::HTMLElement::legend_info = { "HTMLLegendElement", &KJS::HTMLElement::info, &HTMLLegendElementTable, 0 }; const ClassInfo KJS::HTMLElement::ul_info = { "HTMLUListElement", &KJS::HTMLElement::info, &HTMLUListElementTable, 0 }; const ClassInfo KJS::HTMLElement::ol_info = { "HTMLOListElement", &KJS::HTMLElement::info, &HTMLOListElementTable, 0 }; const ClassInfo KJS::HTMLElement::dl_info = { "HTMLDListElement", &KJS::HTMLElement::info, &HTMLDListElementTable, 0 }; const ClassInfo KJS::HTMLElement::dir_info = { "HTMLDirectoryElement", &KJS::HTMLElement::info, &HTMLDirectoryElementTable, 0 }; const ClassInfo KJS::HTMLElement::menu_info = { "HTMLMenuElement", &KJS::HTMLElement::info, &HTMLMenuElementTable, 0 }; const ClassInfo KJS::HTMLElement::li_info = { "HTMLLIElement", &KJS::HTMLElement::info, &HTMLLIElementTable, 0 }; const ClassInfo KJS::HTMLElement::div_info = { "HTMLDivElement", &KJS::HTMLElement::info, &HTMLDivElementTable, 0 }; const ClassInfo KJS::HTMLElement::p_info = { "HTMLParagraphElement", &KJS::HTMLElement::info, &HTMLParagraphElementTable, 0 }; const ClassInfo KJS::HTMLElement::heading_info = { "HTMLHeadingElement", &KJS::HTMLElement::info, &HTMLHeadingElementTable, 0 }; const ClassInfo KJS::HTMLElement::blockQuote_info = { "HTMLBlockQuoteElement", &KJS::HTMLElement::info, &HTMLBlockQuoteElementTable, 0 }; const ClassInfo KJS::HTMLElement::q_info = { "HTMLQuoteElement", &KJS::HTMLElement::info, &HTMLQuoteElementTable, 0 }; const ClassInfo KJS::HTMLElement::pre_info = { "HTMLPreElement", &KJS::HTMLElement::info, &HTMLPreElementTable, 0 }; const ClassInfo KJS::HTMLElement::br_info = { "HTMLBRElement", &KJS::HTMLElement::info, &HTMLBRElementTable, 0 }; const ClassInfo KJS::HTMLElement::baseFont_info = { "HTMLBaseFontElement", &KJS::HTMLElement::info, &HTMLBaseFontElementTable, 0 }; const ClassInfo KJS::HTMLElement::font_info = { "HTMLFontElement", &KJS::HTMLElement::info, &HTMLFontElementTable, 0 }; const ClassInfo KJS::HTMLElement::hr_info = { "HTMLHRElement", &KJS::HTMLElement::info, &HTMLHRElementTable, 0 }; const ClassInfo KJS::HTMLElement::mod_info = { "HTMLModElement", &KJS::HTMLElement::info, &HTMLModElementTable, 0 }; const ClassInfo KJS::HTMLElement::a_info = { "HTMLAnchorElement", &KJS::HTMLElement::info, &HTMLAnchorElementTable, 0 }; const ClassInfo KJS::HTMLElement::canvas_info = { "HTMLCanvasElement", &KJS::HTMLElement::info, &HTMLCanvasElementTable, 0 }; const ClassInfo KJS::HTMLElement::img_info = { "HTMLImageElement", &KJS::HTMLElement::info, &HTMLImageElementTable, 0 }; const ClassInfo KJS::HTMLElement::object_info = { "HTMLObjectElement", &KJS::HTMLElement::info, &HTMLObjectElementTable, 0 }; const ClassInfo KJS::HTMLElement::param_info = { "HTMLParamElement", &KJS::HTMLElement::info, &HTMLParamElementTable, 0 }; const ClassInfo KJS::HTMLElement::applet_info = { "HTMLAppletElement", &KJS::HTMLElement::info, &HTMLAppletElementTable, 0 }; const ClassInfo KJS::HTMLElement::map_info = { "HTMLMapElement", &KJS::HTMLElement::info, &HTMLMapElementTable, 0 }; const ClassInfo KJS::HTMLElement::area_info = { "HTMLAreaElement", &KJS::HTMLElement::info, &HTMLAreaElementTable, 0 }; const ClassInfo KJS::HTMLElement::script_info = { "HTMLScriptElement", &KJS::HTMLElement::info, &HTMLScriptElementTable, 0 }; const ClassInfo KJS::HTMLElement::table_info = { "HTMLTableElement", &KJS::HTMLElement::info, &HTMLTableElementTable, 0 }; const ClassInfo KJS::HTMLElement::caption_info = { "HTMLTableCaptionElement", &KJS::HTMLElement::info, &HTMLTableCaptionElementTable, 0 }; const ClassInfo KJS::HTMLElement::col_info = { "HTMLTableColElement", &KJS::HTMLElement::info, &HTMLTableColElementTable, 0 }; const ClassInfo KJS::HTMLElement::tablesection_info = { "HTMLTableSectionElement", &KJS::HTMLElement::info, &HTMLTableSectionElementTable, 0 }; const ClassInfo KJS::HTMLElement::tr_info = { "HTMLTableRowElement", &KJS::HTMLElement::info, &HTMLTableRowElementTable, 0 }; const ClassInfo KJS::HTMLElement::tablecell_info = { "HTMLTableCellElement", &KJS::HTMLElement::info, &HTMLTableCellElementTable, 0 }; const ClassInfo KJS::HTMLElement::frameSet_info = { "HTMLFrameSetElement", &KJS::HTMLElement::info, &HTMLFrameSetElementTable, 0 }; const ClassInfo KJS::HTMLElement::frame_info = { "HTMLFrameElement", &KJS::HTMLElement::info, &HTMLFrameElementTable, 0 }; const ClassInfo KJS::HTMLElement::iFrame_info = { "HTMLIFrameElement", &KJS::HTMLElement::info, &HTMLIFrameElementTable, 0 }; const ClassInfo KJS::HTMLElement::marquee_info = { "HTMLMarqueeElement", &KJS::HTMLElement::info, 0, 0 }; const ClassInfo KJS::HTMLElement::layer_info = { "HTMLLayerElement", &KJS::HTMLElement::info, &HTMLLayerElementTable, 0 }; static JSObject* prototypeForID(ExecState* exec, DOM::NodeImpl::Id id); KJS::HTMLElement::HTMLElement(ExecState *exec, DOM::HTMLElementImpl* e) : DOMElement(prototypeForID(exec, e->id()), e) { } const ClassInfo* KJS::HTMLElement::classInfo() const { DOM::HTMLElementImpl& element = *impl(); switch (element.id()) { case ID_HTML: return &html_info; case ID_HEAD: return &head_info; case ID_LINK: return &link_info; case ID_TITLE: return &title_info; case ID_META: return &meta_info; case ID_BASE: return &base_info; case ID_ISINDEX: return &isIndex_info; case ID_STYLE: return &style_info; case ID_BODY: return &body_info; case ID_FORM: return &form_info; case ID_SELECT: return &select_info; case ID_OPTGROUP: return &optGroup_info; case ID_OPTION: return &option_info; case ID_INPUT: return &input_info; case ID_TEXTAREA: return &textArea_info; case ID_BUTTON: return &button_info; case ID_LABEL: return &label_info; case ID_FIELDSET: return &fieldSet_info; case ID_LEGEND: return &legend_info; case ID_UL: return &ul_info; case ID_OL: return &ol_info; case ID_DL: return &dl_info; case ID_DIR: return &dir_info; case ID_MENU: return &menu_info; case ID_LI: return &li_info; case ID_DIV: return &div_info; case ID_P: return &p_info; case ID_H1: case ID_H2: case ID_H3: case ID_H4: case ID_H5: case ID_H6: return &heading_info; case ID_BLOCKQUOTE: return &blockQuote_info; case ID_Q: return &q_info; case ID_PRE: return &pre_info; case ID_BR: return &br_info; case ID_BASEFONT: return &baseFont_info; case ID_FONT: return &font_info; case ID_HR: return &hr_info; case ID_INS: case ID_DEL: return &mod_info; case ID_A: return &a_info; case ID_IMG: return &img_info; case ID_CANVAS: return &canvas_info; case ID_OBJECT: return &object_info; case ID_PARAM: return ¶m_info; case ID_APPLET: return &applet_info; case ID_MAP: return &map_info; case ID_AREA: return &area_info; case ID_SCRIPT: return &script_info; case ID_TABLE: return &table_info; case ID_CAPTION: return &caption_info; case ID_COL: case ID_COLGROUP: return &col_info; case ID_THEAD: case ID_TBODY: case ID_TFOOT: return &tablesection_info; case ID_TR: return &tr_info; case ID_TH: case ID_TD: return &tablecell_info; case ID_FRAMESET: return &frameSet_info; case ID_FRAME: return &frame_info; case ID_IFRAME: return &iFrame_info; case ID_MARQUEE: return &marquee_info; case ID_LAYER: return &layer_info; default: return &info; } } /* @begin HTMLElementTable 11 id KJS::HTMLElement::ElementId DontDelete title KJS::HTMLElement::ElementTitle DontDelete lang KJS::HTMLElement::ElementLang DontDelete dir KJS::HTMLElement::ElementDir DontDelete ### isn't this "class" in the HTML spec? className KJS::HTMLElement::ElementClassName DontDelete innerHTML KJS::HTMLElement::ElementInnerHTML DontDelete innerText KJS::HTMLElement::ElementInnerText DontDelete document KJS::HTMLElement::ElementDocument DontDelete|ReadOnly # IE extension children KJS::HTMLElement::ElementChildren DontDelete|ReadOnly all KJS::HTMLElement::ElementAll DontDelete|ReadOnly @end @begin HTMLElementProtoTable 1 scrollIntoView KJS::HTMLElement::ElementScrollIntoView DontDelete|Function 0 @end @begin HTMLHtmlElementTable 1 version KJS::HTMLElement::HtmlVersion DontDelete @end @begin HTMLHeadElementTable 1 profile KJS::HTMLElement::HeadProfile DontDelete @end @begin HTMLLinkElementTable 11 disabled KJS::HTMLElement::LinkDisabled DontDelete charset KJS::HTMLElement::LinkCharset DontDelete href KJS::HTMLElement::LinkHref DontDelete hreflang KJS::HTMLElement::LinkHrefLang DontDelete media KJS::HTMLElement::LinkMedia DontDelete rel KJS::HTMLElement::LinkRel DontDelete rev KJS::HTMLElement::LinkRev DontDelete target KJS::HTMLElement::LinkTarget DontDelete type KJS::HTMLElement::LinkType DontDelete sheet KJS::HTMLElement::LinkSheet DontDelete|ReadOnly @end @begin HTMLTitleElementTable 1 text KJS::HTMLElement::TitleText DontDelete @end @begin HTMLMetaElementTable 4 content KJS::HTMLElement::MetaContent DontDelete httpEquiv KJS::HTMLElement::MetaHttpEquiv DontDelete name KJS::HTMLElement::MetaName DontDelete scheme KJS::HTMLElement::MetaScheme DontDelete @end @begin HTMLBaseElementTable 2 href KJS::HTMLElement::BaseHref DontDelete target KJS::HTMLElement::BaseTarget DontDelete @end @begin HTMLIsIndexElementTable 2 form KJS::HTMLElement::IsIndexForm DontDelete|ReadOnly prompt KJS::HTMLElement::IsIndexPrompt DontDelete @end @begin HTMLStyleElementTable 4 disabled KJS::HTMLElement::StyleDisabled DontDelete media KJS::HTMLElement::StyleMedia DontDelete type KJS::HTMLElement::StyleType DontDelete sheet KJS::HTMLElement::StyleSheet DontDelete|ReadOnly @end @begin HTMLBodyElementTable 8 aLink KJS::HTMLElement::BodyALink DontDelete background KJS::HTMLElement::BodyBackground DontDelete bgColor KJS::HTMLElement::BodyBgColor DontDelete link KJS::HTMLElement::BodyLink DontDelete text KJS::HTMLElement::BodyText DontDelete vLink KJS::HTMLElement::BodyVLink DontDelete # IE extension onload KJS::HTMLElement::BodyOnLoad DontDelete @end @begin HTMLFormElementTable 11 # Also supported, by name/index elements KJS::HTMLElement::FormElements DontDelete|ReadOnly length KJS::HTMLElement::FormLength DontDelete|ReadOnly name KJS::HTMLElement::FormName DontDelete acceptCharset KJS::HTMLElement::FormAcceptCharset DontDelete action KJS::HTMLElement::FormAction DontDelete encoding KJS::HTMLElement::FormEncType DontDelete enctype KJS::HTMLElement::FormEncType DontDelete method KJS::HTMLElement::FormMethod DontDelete target KJS::HTMLElement::FormTarget DontDelete @end @begin HTMLFormElementProtoTable 2 submit KJS::HTMLElement::FormSubmit DontDelete|Function 0 reset KJS::HTMLElement::FormReset DontDelete|Function 0 @end @begin HTMLSelectElementTable 11 # Also supported, by index type KJS::HTMLElement::SelectType DontDelete|ReadOnly selectedIndex KJS::HTMLElement::SelectSelectedIndex DontDelete value KJS::HTMLElement::SelectValue DontDelete length KJS::HTMLElement::SelectLength DontDelete form KJS::HTMLElement::SelectForm DontDelete|ReadOnly options KJS::HTMLElement::SelectOptions DontDelete|ReadOnly disabled KJS::HTMLElement::SelectDisabled DontDelete multiple KJS::HTMLElement::SelectMultiple DontDelete name KJS::HTMLElement::SelectName DontDelete size KJS::HTMLElement::SelectSize DontDelete tabIndex KJS::HTMLElement::SelectTabIndex DontDelete @end @begin HTMLSelectElementProtoTable 4 add KJS::HTMLElement::SelectAdd DontDelete|Function 2 remove KJS::HTMLElement::SelectRemove DontDelete|Function 1 blur KJS::HTMLElement::SelectBlur DontDelete|Function 0 focus KJS::HTMLElement::SelectFocus DontDelete|Function 0 @end @begin HTMLOptGroupElementTable 2 disabled KJS::HTMLElement::OptGroupDisabled DontDelete label KJS::HTMLElement::OptGroupLabel DontDelete @end @begin HTMLOptionElementTable 8 form KJS::HTMLElement::OptionForm DontDelete|ReadOnly defaultSelected KJS::HTMLElement::OptionDefaultSelected DontDelete text KJS::HTMLElement::OptionText DontDelete index KJS::HTMLElement::OptionIndex DontDelete|ReadOnly disabled KJS::HTMLElement::OptionDisabled DontDelete label KJS::HTMLElement::OptionLabel DontDelete selected KJS::HTMLElement::OptionSelected DontDelete value KJS::HTMLElement::OptionValue DontDelete @end @begin HTMLInputElementTable 25 defaultValue KJS::HTMLElement::InputDefaultValue DontDelete defaultChecked KJS::HTMLElement::InputDefaultChecked DontDelete form KJS::HTMLElement::InputForm DontDelete|ReadOnly accept KJS::HTMLElement::InputAccept DontDelete accessKey KJS::HTMLElement::InputAccessKey DontDelete align KJS::HTMLElement::InputAlign DontDelete alt KJS::HTMLElement::InputAlt DontDelete checked KJS::HTMLElement::InputChecked DontDelete indeterminate KJS::HTMLElement::InputIndeterminate DontDelete status KJS::HTMLElement::InputChecked DontDelete disabled KJS::HTMLElement::InputDisabled DontDelete maxLength KJS::HTMLElement::InputMaxLength DontDelete name KJS::HTMLElement::InputName DontDelete readOnly KJS::HTMLElement::InputReadOnly DontDelete size KJS::HTMLElement::InputSize DontDelete src KJS::HTMLElement::InputSrc DontDelete tabIndex KJS::HTMLElement::InputTabIndex DontDelete type KJS::HTMLElement::InputType DontDelete useMap KJS::HTMLElement::InputUseMap DontDelete value KJS::HTMLElement::InputValue DontDelete selectionStart KJS::HTMLElement::InputSelectionStart DontDelete selectionEnd KJS::HTMLElement::InputSelectionEnd DontDelete @end @begin HTMLInputElementProtoTable 5 blur KJS::HTMLElement::InputBlur DontDelete|Function 0 focus KJS::HTMLElement::InputFocus DontDelete|Function 0 select KJS::HTMLElement::InputSelect DontDelete|Function 0 click KJS::HTMLElement::InputClick DontDelete|Function 0 setSelectionRange KJS::HTMLElement::InputSetSelectionRange DontDelete|Function 2 @end @begin HTMLTextAreaElementTable 13 defaultValue KJS::HTMLElement::TextAreaDefaultValue DontDelete form KJS::HTMLElement::TextAreaForm DontDelete|ReadOnly accessKey KJS::HTMLElement::TextAreaAccessKey DontDelete cols KJS::HTMLElement::TextAreaCols DontDelete disabled KJS::HTMLElement::TextAreaDisabled DontDelete name KJS::HTMLElement::TextAreaName DontDelete readOnly KJS::HTMLElement::TextAreaReadOnly DontDelete rows KJS::HTMLElement::TextAreaRows DontDelete tabIndex KJS::HTMLElement::TextAreaTabIndex DontDelete type KJS::HTMLElement::TextAreaType DontDelete|ReadOnly value KJS::HTMLElement::TextAreaValue DontDelete selectionStart KJS::HTMLElement::TextAreaSelectionStart DontDelete selectionEnd KJS::HTMLElement::TextAreaSelectionEnd DontDelete textLength KJS::HTMLElement::TextAreaTextLength DontDelete|ReadOnly @end @begin HTMLTextAreaElementProtoTable 4 blur KJS::HTMLElement::TextAreaBlur DontDelete|Function 0 focus KJS::HTMLElement::TextAreaFocus DontDelete|Function 0 select KJS::HTMLElement::TextAreaSelect DontDelete|Function 0 setSelectionRange KJS::HTMLElement::TextAreaSetSelectionRange DontDelete|Function 2 @end @begin HTMLButtonElementTable 9 form KJS::HTMLElement::ButtonForm DontDelete|ReadOnly accessKey KJS::HTMLElement::ButtonAccessKey DontDelete disabled KJS::HTMLElement::ButtonDisabled DontDelete name KJS::HTMLElement::ButtonName DontDelete tabIndex KJS::HTMLElement::ButtonTabIndex DontDelete type KJS::HTMLElement::ButtonType DontDelete|ReadOnly value KJS::HTMLElement::ButtonValue DontDelete @end @begin HTMLButtonElementProtoTable 2 blur KJS::HTMLElement::ButtonBlur DontDelete|Function 0 focus KJS::HTMLElement::ButtonFocus DontDelete|Function 0 @end @begin HTMLLabelElementTable 3 form KJS::HTMLElement::LabelForm DontDelete|ReadOnly accessKey KJS::HTMLElement::LabelAccessKey DontDelete htmlFor KJS::HTMLElement::LabelHtmlFor DontDelete @end @begin HTMLFieldSetElementTable 1 form KJS::HTMLElement::FieldSetForm DontDelete|ReadOnly @end @begin HTMLLegendElementTable 3 form KJS::HTMLElement::LegendForm DontDelete|ReadOnly accessKey KJS::HTMLElement::LegendAccessKey DontDelete align KJS::HTMLElement::LegendAlign DontDelete @end @begin HTMLUListElementTable 2 compact KJS::HTMLElement::UListCompact DontDelete type KJS::HTMLElement::UListType DontDelete @end @begin HTMLOListElementTable 3 compact KJS::HTMLElement::OListCompact DontDelete start KJS::HTMLElement::OListStart DontDelete type KJS::HTMLElement::OListType DontDelete @end @begin HTMLDListElementTable 1 compact KJS::HTMLElement::DListCompact DontDelete @end @begin HTMLDirectoryElementTable 1 compact KJS::HTMLElement::DirectoryCompact DontDelete @end @begin HTMLMenuElementTable 1 compact KJS::HTMLElement::MenuCompact DontDelete @end @begin HTMLLIElementTable 2 type KJS::HTMLElement::LIType DontDelete value KJS::HTMLElement::LIValue DontDelete @end @begin HTMLDivElementTable 1 align KJS::HTMLElement::DivAlign DontDelete @end @begin HTMLParagraphElementTable 1 align KJS::HTMLElement::ParagraphAlign DontDelete @end @begin HTMLHeadingElementTable 1 align KJS::HTMLElement::HeadingAlign DontDelete @end @begin HTMLBlockQuoteElementTable 1 cite KJS::HTMLElement::BlockQuoteCite DontDelete @end @begin HTMLQuoteElementTable 1 cite KJS::HTMLElement::QuoteCite DontDelete @end @begin HTMLPreElementTable 1 width KJS::HTMLElement::PreWidth DontDelete @end @begin HTMLBRElementTable 1 clear KJS::HTMLElement::BRClear DontDelete @end @begin HTMLBaseFontElementTable 3 color KJS::HTMLElement::BaseFontColor DontDelete face KJS::HTMLElement::BaseFontFace DontDelete size KJS::HTMLElement::BaseFontSize DontDelete @end @begin HTMLFontElementTable 3 color KJS::HTMLElement::FontColor DontDelete face KJS::HTMLElement::FontFace DontDelete size KJS::HTMLElement::FontSize DontDelete @end @begin HTMLHRElementTable 4 align KJS::HTMLElement::HRAlign DontDelete noShade KJS::HTMLElement::HRNoShade DontDelete size KJS::HTMLElement::HRSize DontDelete width KJS::HTMLElement::HRWidth DontDelete @end @begin HTMLModElementTable 2 cite KJS::HTMLElement::ModCite DontDelete dateTime KJS::HTMLElement::ModDateTime DontDelete @end @begin HTMLAnchorElementTable 23 accessKey KJS::HTMLElement::AnchorAccessKey DontDelete charset KJS::HTMLElement::AnchorCharset DontDelete coords KJS::HTMLElement::AnchorCoords DontDelete href KJS::HTMLElement::AnchorHref DontDelete hreflang KJS::HTMLElement::AnchorHrefLang DontDelete hash KJS::HTMLElement::AnchorHash DontDelete|ReadOnly host KJS::HTMLElement::AnchorHost DontDelete|ReadOnly hostname KJS::HTMLElement::AnchorHostname DontDelete|ReadOnly name KJS::HTMLElement::AnchorName DontDelete pathname KJS::HTMLElement::AnchorPathName DontDelete|ReadOnly port KJS::HTMLElement::AnchorPort DontDelete|ReadOnly protocol KJS::HTMLElement::AnchorProtocol DontDelete|ReadOnly rel KJS::HTMLElement::AnchorRel DontDelete rev KJS::HTMLElement::AnchorRev DontDelete search KJS::HTMLElement::AnchorSearch DontDelete shape KJS::HTMLElement::AnchorShape DontDelete tabIndex KJS::HTMLElement::AnchorTabIndex DontDelete target KJS::HTMLElement::AnchorTarget DontDelete text KJS::HTMLElement::AnchorText DontDelete|ReadOnly type KJS::HTMLElement::AnchorType DontDelete @end @begin HTMLAnchorElementProtoTable 3 blur KJS::HTMLElement::AnchorBlur DontDelete|Function 0 focus KJS::HTMLElement::AnchorFocus DontDelete|Function 0 click KJS::HTMLElement::AnchorClick DontDelete|Function 0 @end @begin HTMLImageElementTable 15 name KJS::HTMLElement::ImageName DontDelete align KJS::HTMLElement::ImageAlign DontDelete alt KJS::HTMLElement::ImageAlt DontDelete border KJS::HTMLElement::ImageBorder DontDelete complete KJS::HTMLElement::ImageComplete DontDelete|ReadOnly height KJS::HTMLElement::ImageHeight DontDelete hspace KJS::HTMLElement::ImageHspace DontDelete isMap KJS::HTMLElement::ImageIsMap DontDelete longDesc KJS::HTMLElement::ImageLongDesc DontDelete src KJS::HTMLElement::ImageSrc DontDelete useMap KJS::HTMLElement::ImageUseMap DontDelete vspace KJS::HTMLElement::ImageVspace DontDelete width KJS::HTMLElement::ImageWidth DontDelete x KJS::HTMLElement::ImageX DontDelete|ReadOnly y KJS::HTMLElement::ImageY DontDelete|ReadOnly @end @begin HTMLObjectElementTable 20 form KJS::HTMLElement::ObjectForm DontDelete|ReadOnly code KJS::HTMLElement::ObjectCode DontDelete align KJS::HTMLElement::ObjectAlign DontDelete archive KJS::HTMLElement::ObjectArchive DontDelete border KJS::HTMLElement::ObjectBorder DontDelete codeBase KJS::HTMLElement::ObjectCodeBase DontDelete codeType KJS::HTMLElement::ObjectCodeType DontDelete contentDocument KJS::HTMLElement::ObjectContentDocument DontDelete|ReadOnly data KJS::HTMLElement::ObjectData DontDelete declare KJS::HTMLElement::ObjectDeclare DontDelete height KJS::HTMLElement::ObjectHeight DontDelete hspace KJS::HTMLElement::ObjectHspace DontDelete name KJS::HTMLElement::ObjectName DontDelete standby KJS::HTMLElement::ObjectStandby DontDelete tabIndex KJS::HTMLElement::ObjectTabIndex DontDelete type KJS::HTMLElement::ObjectType DontDelete useMap KJS::HTMLElement::ObjectUseMap DontDelete vspace KJS::HTMLElement::ObjectVspace DontDelete width KJS::HTMLElement::ObjectWidth DontDelete @end @begin HTMLParamElementTable 4 name KJS::HTMLElement::ParamName DontDelete type KJS::HTMLElement::ParamType DontDelete value KJS::HTMLElement::ParamValue DontDelete valueType KJS::HTMLElement::ParamValueType DontDelete @end @begin HTMLAppletElementTable 11 align KJS::HTMLElement::AppletAlign DontDelete alt KJS::HTMLElement::AppletAlt DontDelete archive KJS::HTMLElement::AppletArchive DontDelete code KJS::HTMLElement::AppletCode DontDelete codeBase KJS::HTMLElement::AppletCodeBase DontDelete height KJS::HTMLElement::AppletHeight DontDelete hspace KJS::HTMLElement::AppletHspace DontDelete name KJS::HTMLElement::AppletName DontDelete object KJS::HTMLElement::AppletObject DontDelete vspace KJS::HTMLElement::AppletVspace DontDelete width KJS::HTMLElement::AppletWidth DontDelete @end @begin HTMLMapElementTable 2 areas KJS::HTMLElement::MapAreas DontDelete|ReadOnly name KJS::HTMLElement::MapName DontDelete @end @begin HTMLAreaElementTable 15 accessKey KJS::HTMLElement::AreaAccessKey DontDelete alt KJS::HTMLElement::AreaAlt DontDelete coords KJS::HTMLElement::AreaCoords DontDelete href KJS::HTMLElement::AreaHref DontDelete hash KJS::HTMLElement::AreaHash DontDelete|ReadOnly host KJS::HTMLElement::AreaHost DontDelete|ReadOnly hostname KJS::HTMLElement::AreaHostName DontDelete|ReadOnly pathname KJS::HTMLElement::AreaPathName DontDelete|ReadOnly port KJS::HTMLElement::AreaPort DontDelete|ReadOnly protocol KJS::HTMLElement::AreaProtocol DontDelete|ReadOnly search KJS::HTMLElement::AreaSearch DontDelete|ReadOnly noHref KJS::HTMLElement::AreaNoHref DontDelete shape KJS::HTMLElement::AreaShape DontDelete tabIndex KJS::HTMLElement::AreaTabIndex DontDelete target KJS::HTMLElement::AreaTarget DontDelete @end @begin HTMLScriptElementTable 7 text KJS::HTMLElement::ScriptText DontDelete htmlFor KJS::HTMLElement::ScriptHtmlFor DontDelete event KJS::HTMLElement::ScriptEvent DontDelete charset KJS::HTMLElement::ScriptCharset DontDelete defer KJS::HTMLElement::ScriptDefer DontDelete src KJS::HTMLElement::ScriptSrc DontDelete type KJS::HTMLElement::ScriptType DontDelete @end @begin HTMLTableElementTable 23 caption KJS::HTMLElement::TableCaption DontDelete tHead KJS::HTMLElement::TableTHead DontDelete tFoot KJS::HTMLElement::TableTFoot DontDelete rows KJS::HTMLElement::TableRows DontDelete|ReadOnly tBodies KJS::HTMLElement::TableTBodies DontDelete|ReadOnly align KJS::HTMLElement::TableAlign DontDelete bgColor KJS::HTMLElement::TableBgColor DontDelete border KJS::HTMLElement::TableBorder DontDelete cellPadding KJS::HTMLElement::TableCellPadding DontDelete cellSpacing KJS::HTMLElement::TableCellSpacing DontDelete frame KJS::HTMLElement::TableFrame DontDelete rules KJS::HTMLElement::TableRules DontDelete summary KJS::HTMLElement::TableSummary DontDelete width KJS::HTMLElement::TableWidth DontDelete @end @begin HTMLTableElementProtoTable 8 createTHead KJS::HTMLElement::TableCreateTHead DontDelete|Function 0 deleteTHead KJS::HTMLElement::TableDeleteTHead DontDelete|Function 0 createTFoot KJS::HTMLElement::TableCreateTFoot DontDelete|Function 0 deleteTFoot KJS::HTMLElement::TableDeleteTFoot DontDelete|Function 0 createCaption KJS::HTMLElement::TableCreateCaption DontDelete|Function 0 deleteCaption KJS::HTMLElement::TableDeleteCaption DontDelete|Function 0 insertRow KJS::HTMLElement::TableInsertRow DontDelete|Function 1 deleteRow KJS::HTMLElement::TableDeleteRow DontDelete|Function 1 @end @begin HTMLTableCaptionElementTable 1 align KJS::HTMLElement::TableCaptionAlign DontDelete @end @begin HTMLTableColElementTable 7 align KJS::HTMLElement::TableColAlign DontDelete ch KJS::HTMLElement::TableColCh DontDelete chOff KJS::HTMLElement::TableColChOff DontDelete span KJS::HTMLElement::TableColSpan DontDelete vAlign KJS::HTMLElement::TableColVAlign DontDelete width KJS::HTMLElement::TableColWidth DontDelete @end @begin HTMLTableSectionElementTable 7 align KJS::HTMLElement::TableSectionAlign DontDelete ch KJS::HTMLElement::TableSectionCh DontDelete chOff KJS::HTMLElement::TableSectionChOff DontDelete vAlign KJS::HTMLElement::TableSectionVAlign DontDelete rows KJS::HTMLElement::TableSectionRows DontDelete|ReadOnly @end @begin HTMLTableSectionElementProtoTable 2 insertRow KJS::HTMLElement::TableSectionInsertRow DontDelete|Function 1 deleteRow KJS::HTMLElement::TableSectionDeleteRow DontDelete|Function 1 @end @begin HTMLTableRowElementTable 11 rowIndex KJS::HTMLElement::TableRowRowIndex DontDelete|ReadOnly sectionRowIndex KJS::HTMLElement::TableRowSectionRowIndex DontDelete|ReadOnly cells KJS::HTMLElement::TableRowCells DontDelete|ReadOnly align KJS::HTMLElement::TableRowAlign DontDelete bgColor KJS::HTMLElement::TableRowBgColor DontDelete ch KJS::HTMLElement::TableRowCh DontDelete chOff KJS::HTMLElement::TableRowChOff DontDelete vAlign KJS::HTMLElement::TableRowVAlign DontDelete @end @begin HTMLTableRowElementProtoTable 2 insertCell KJS::HTMLElement::TableRowInsertCell DontDelete|Function 1 deleteCell KJS::HTMLElement::TableRowDeleteCell DontDelete|Function 1 @end @begin HTMLTableCellElementTable 15 cellIndex KJS::HTMLElement::TableCellCellIndex DontDelete|ReadOnly abbr KJS::HTMLElement::TableCellAbbr DontDelete align KJS::HTMLElement::TableCellAlign DontDelete axis KJS::HTMLElement::TableCellAxis DontDelete bgColor KJS::HTMLElement::TableCellBgColor DontDelete ch KJS::HTMLElement::TableCellCh DontDelete chOff KJS::HTMLElement::TableCellChOff DontDelete colSpan KJS::HTMLElement::TableCellColSpan DontDelete headers KJS::HTMLElement::TableCellHeaders DontDelete height KJS::HTMLElement::TableCellHeight DontDelete noWrap KJS::HTMLElement::TableCellNoWrap DontDelete rowSpan KJS::HTMLElement::TableCellRowSpan DontDelete scope KJS::HTMLElement::TableCellScope DontDelete vAlign KJS::HTMLElement::TableCellVAlign DontDelete width KJS::HTMLElement::TableCellWidth DontDelete @end @begin HTMLFrameSetElementTable 2 cols KJS::HTMLElement::FrameSetCols DontDelete rows KJS::HTMLElement::FrameSetRows DontDelete @end @begin HTMLLayerElementTable 6 top KJS::HTMLElement::LayerTop DontDelete left KJS::HTMLElement::LayerLeft DontDelete visibility KJS::HTMLElement::LayerVisibility DontDelete bgColor KJS::HTMLElement::LayerBgColor DontDelete document KJS::HTMLElement::LayerDocument DontDelete|ReadOnly clip KJS::HTMLElement::LayerClip DontDelete|ReadOnly layers KJS::HTMLElement::LayerLayers DontDelete|ReadOnly @end @begin HTMLFrameElementTable 13 contentDocument KJS::HTMLElement::FrameContentDocument DontDelete|ReadOnly contentWindow KJS::HTMLElement::FrameContentWindow DontDelete|ReadOnly frameBorder KJS::HTMLElement::FrameFrameBorder DontDelete longDesc KJS::HTMLElement::FrameLongDesc DontDelete marginHeight KJS::HTMLElement::FrameMarginHeight DontDelete marginWidth KJS::HTMLElement::FrameMarginWidth DontDelete name KJS::HTMLElement::FrameName DontDelete noResize KJS::HTMLElement::FrameNoResize DontDelete scrolling KJS::HTMLElement::FrameScrolling DontDelete src KJS::HTMLElement::FrameSrc DontDelete location KJS::HTMLElement::FrameLocation DontDelete # IE extension width KJS::HTMLElement::FrameWidth DontDelete|ReadOnly height KJS::HTMLElement::FrameHeight DontDelete|ReadOnly @end @begin HTMLIFrameElementTable 12 align KJS::HTMLElement::IFrameAlign DontDelete contentDocument KJS::HTMLElement::IFrameContentDocument DontDelete|ReadOnly contentWindow KJS::HTMLElement::IFrameContentWindow DontDelete|ReadOnly frameBorder KJS::HTMLElement::IFrameFrameBorder DontDelete height KJS::HTMLElement::IFrameHeight DontDelete longDesc KJS::HTMLElement::IFrameLongDesc DontDelete marginHeight KJS::HTMLElement::IFrameMarginHeight DontDelete marginWidth KJS::HTMLElement::IFrameMarginWidth DontDelete name KJS::HTMLElement::IFrameName DontDelete scrolling KJS::HTMLElement::IFrameScrolling DontDelete src KJS::HTMLElement::IFrameSrc DontDelete width KJS::HTMLElement::IFrameWidth DontDelete @end @begin HTMLMarqueeElementProtoTable 2 start KJS::HTMLElement::MarqueeStart DontDelete|Function 0 stop KJS::HTMLElement::MarqueeStop DontDelete|Function 0 @end @begin HTMLCanvasElementTable 2 width KJS::HTMLElement::CanvasWidth DontDelete height KJS::HTMLElement::CanvasHeight DontDelete @end @begin HTMLCanvasElementProtoTable 1 getContext KJS::HTMLElement::CanvasGetContext DontDelete|Function 1 toDataURL KJS::HTMLElement::CanvasToDataURL DontDelete|Function 0 @end */ KJS_IMPLEMENT_PROTOFUNC(HTMLElementFunction) KParts::LiveConnectExtension *HTMLElement::getLiveConnectExtension(const DOM::HTMLElementImpl &element) { DOM::DocumentImpl* doc = element.getDocument(); KHTMLView *view = doc->view(); if (view) return view->part()->liveConnectExtension(&element); return 0L; } JSValue *HTMLElement::formNameGetter(ExecState *exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot) { HTMLElement *thisObj = static_cast(slot.slotBase()); KJS::HTMLCollection coll(exec, static_cast(thisObj->impl())->elements()); return coll.getNamedItems(exec, propertyName); } //JSValue* KJS::HTMLElement::tryGet(ExecState *exec, const Identifier &propertyName) const bool KJS::HTMLElement::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot& slot) { DOM::HTMLElementImpl& element = *impl(); #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLElement::getOwnPropertySlot " << propertyName.qstring() << " thisTag=" << element.tagName().string(); #endif // First look at dynamic properties switch (element.id()) { case ID_FORM: { DOM::HTMLFormElementImpl& form = static_cast(element); // Check if we're retrieving an element (by index or by name) if (getIndexSlot(this, propertyName, slot)) return true; KJS::HTMLCollection coll(exec, form.elements()); JSValue *namedItems = coll.getNamedItems(exec, propertyName); if (namedItems->type() != UndefinedType) { slot.setCustom(this, formNameGetter); return namedItems; } break; } case ID_SELECT: if (getIndexSlot(this, propertyName, slot)) return true; break; case ID_APPLET: case ID_OBJECT: case ID_EMBED: { KParts::LiveConnectExtension *lc = getLiveConnectExtension(*impl()); QString rvalue; KParts::LiveConnectExtension::Type rtype; unsigned long robjid; if (lc && lc->get(0, propertyName.qstring(), rtype, robjid, rvalue)) return getImmediateValueSlot(this, getLiveConnectValue(lc, propertyName.qstring(), rtype, rvalue, robjid), slot); break; } } const HashTable* table = classInfo()->propHashTable; // get the right hashtable if (table && getStaticOwnPropertySlot(table, this, propertyName, slot)) return true; // Base HTMLElement stuff or parent class forward, as usual return getStaticPropertySlot( exec, &KJS::HTMLElementTable, this, propertyName, slot); } JSValue* HTMLElement::indexGetter(ExecState *exec, unsigned index) { switch (impl()->id()) { case ID_FORM: { DOM::HTMLFormElementImpl* form = static_cast(impl()); SharedPtr elems = form->elements(); return getDOMNode(exec, elems->item(index)); } case ID_SELECT: { DOM::HTMLSelectElementImpl* select = static_cast(impl()); SharedPtr opts = select->options(); return getDOMNode(exec, opts->item(index)); // not specified by DOM(?) but supported in netscape/IE } default: assert(0); return jsUndefined(); } } #if 0 // First look at dynamic properties switch (element.id()) { case ID_FORM: { DOM::HTMLFormElementImpl& form = static_cast(element); // Check if we're retrieving an element (by index or by name) KJS::HTMLCollection coll(exec, form.elements()); JSValue *namedItems = coll.getNamedItems(exec, propertyName); if (namedItems->type() != UndefinedType) return namedItems; } } #endif /** Table of how to connect JS tokens to attributes */ const KJS::HTMLElement::BoundPropInfo KJS::HTMLElement::bpTable[] = { {ID_HTML, HtmlVersion, T_String, ATTR_VERSION}, {ID_HEAD, HeadProfile, T_String, ATTR_PROFILE}, {ID_LINK, LinkDisabled, T_Bool, ATTR_DISABLED}, {ID_LINK, LinkCharset, T_String, ATTR_CHARSET}, {ID_LINK, LinkHref, T_URL, ATTR_HREF}, {ID_LINK, LinkHrefLang, T_String, ATTR_HREFLANG}, {ID_LINK, LinkMedia, T_String, ATTR_MEDIA}, {ID_LINK, LinkRel, T_String, ATTR_REL}, {ID_LINK, LinkRev, T_String, ATTR_REV}, {ID_LINK, LinkTarget, T_String, ATTR_TARGET}, {ID_LINK, LinkType, T_String, ATTR_TYPE}, {ID_BASE, BaseHref, T_URL, ATTR_HREF}, {ID_BASE, BaseTarget, T_String, ATTR_TARGET}, {ID_META, MetaContent, T_String, ATTR_CONTENT}, {ID_META, MetaHttpEquiv,T_String, ATTR_HTTP_EQUIV}, {ID_META, MetaName, T_String, ATTR_NAME}, {ID_META, MetaScheme, T_String, ATTR_SCHEME}, {ID_STYLE, StyleDisabled, T_Bool, ATTR_DISABLED}, {ID_STYLE, StyleMedia, T_String, ATTR_MEDIA}, {ID_STYLE, StyleType, T_String, ATTR_TYPE}, {ID_BODY, BodyALink, T_String, ATTR_ALINK}, {ID_BODY, BodyBackground, T_String, ATTR_BACKGROUND}, {ID_BODY, BodyBgColor, T_String, ATTR_BGCOLOR}, {ID_BODY, BodyLink, T_String, ATTR_LINK}, {ID_BODY, BodyText, T_String, ATTR_TEXT},//### odd? {ID_BODY, BodyVLink, T_String, ATTR_VLINK}, {ID_FORM, FormName, T_String, ATTR_NAME}, // NOT getString (IE gives empty string) {ID_FORM, FormAcceptCharset, T_String, ATTR_ACCEPT_CHARSET}, {ID_FORM, FormAction, T_String, ATTR_ACTION}, {ID_FORM, FormEncType, T_String, ATTR_ENCTYPE}, {ID_FORM, FormMethod, T_String, ATTR_METHOD}, {ID_FORM, FormTarget, T_String, ATTR_TARGET}, {ID_SELECT, SelectDisabled, T_Bool, ATTR_DISABLED}, {ID_SELECT, SelectMultiple, T_Bool, ATTR_MULTIPLE}, {ID_SELECT, SelectSize, T_Int, ATTR_SIZE}, //toInt on attr, then number {ID_SELECT, SelectTabIndex, T_TabIdx, NotApplicable}, {ID_OPTGROUP, OptGroupDisabled, T_Bool, ATTR_DISABLED}, {ID_OPTGROUP, OptGroupLabel, T_String, ATTR_LABEL}, {ID_OPTION, OptionDefaultSelected, T_Bool, ATTR_SELECTED}, {ID_OPTION, OptionDisabled, T_Bool, ATTR_DISABLED}, {ID_OPTION, OptionLabel, T_String, ATTR_LABEL}, {ID_INPUT, InputDefaultValue, T_String, ATTR_VALUE}, {ID_INPUT, InputDefaultChecked, T_Bool, ATTR_CHECKED}, {ID_INPUT, InputAccept, T_String, ATTR_ACCEPT}, {ID_INPUT, InputAccessKey, T_String, ATTR_ACCESSKEY}, {ID_INPUT, InputAlign, T_String, ATTR_ALIGN}, {ID_INPUT, InputAlt, T_String, ATTR_ALT}, {ID_INPUT, InputDisabled, T_Bool, ATTR_DISABLED}, {ID_INPUT, InputMaxLength, T_Int, ATTR_MAXLENGTH}, {ID_INPUT, InputReadOnly, T_Bool, ATTR_READONLY}, {ID_INPUT, InputSize, T_Int, ATTR_SIZE}, {ID_INPUT, InputSrc, T_URL, ATTR_SRC}, {ID_INPUT, InputTabIndex, T_TabIdx, NotApplicable}, {ID_INPUT, InputUseMap, T_String, ATTR_USEMAP}, {ID_TEXTAREA, TextAreaAccessKey, T_String, ATTR_ACCESSKEY}, {ID_TEXTAREA, TextAreaCols, T_Int, ATTR_COLS}, {ID_TEXTAREA, TextAreaDisabled, T_Bool, ATTR_DISABLED}, {ID_TEXTAREA, TextAreaReadOnly, T_Bool, ATTR_READONLY}, {ID_TEXTAREA, TextAreaRows, T_Int, ATTR_ROWS}, {ID_TEXTAREA, TextAreaTabIndex, T_TabIdx, NotApplicable}, {ID_BUTTON, ButtonAccessKey, T_String, ATTR_ACCESSKEY}, {ID_BUTTON, ButtonDisabled, T_Bool , ATTR_DISABLED}, {ID_BUTTON, ButtonName, T_String, ATTR_NAME}, {ID_BUTTON, ButtonTabIndex, T_TabIdx, NotApplicable}, {ID_BUTTON, ButtonValue, T_String, ATTR_VALUE}, {ID_LABEL, LabelAccessKey, T_String, ATTR_ACCESSKEY}, {ID_LABEL, LabelHtmlFor, T_String, ATTR_FOR}, {ID_LEGEND, LegendAccessKey, T_String, ATTR_ACCESSKEY}, {ID_LEGEND, LegendAlign, T_String, ATTR_ALIGN}, {ID_UL, UListCompact, T_Bool, ATTR_COMPACT}, {ID_UL, UListType, T_String, ATTR_TYPE}, {ID_OL, OListCompact, T_Bool, ATTR_COMPACT}, {ID_OL, OListStart, T_Int, ATTR_START}, {ID_OL, OListType, T_String, ATTR_TYPE}, {ID_DL, DListCompact, T_Bool, ATTR_COMPACT}, {ID_DIR, DirectoryCompact, T_Bool, ATTR_COMPACT}, {ID_MENU, MenuCompact, T_Bool, ATTR_COMPACT}, {ID_LI, LIType, T_String, ATTR_TYPE}, {ID_LI, LIValue, T_Int, ATTR_VALUE}, {ID_DIV, DivAlign, T_String, ATTR_ALIGN}, {ID_P, ParagraphAlign, T_String, ATTR_ALIGN}, {NotApplicable,HeadingAlign, T_String, ATTR_ALIGN}, {ID_BLOCKQUOTE, BlockQuoteCite, T_String, ATTR_CITE}, {ID_Q, QuoteCite, T_String, ATTR_CITE}, {ID_PRE, PreWidth, T_Int, ATTR_WIDTH}, {ID_BR, BRClear, T_String, ATTR_CLEAR}, {ID_BASEFONT, BaseFontColor, T_String, ATTR_COLOR}, {ID_BASEFONT, BaseFontFace, T_String, ATTR_FACE}, {ID_BASEFONT, BaseFontSize, T_Int, ATTR_SIZE}, {ID_FONT, FontColor, T_String, ATTR_COLOR}, {ID_FONT, FontFace, T_String, ATTR_FACE}, {ID_FONT, FontSize, T_String, ATTR_SIZE}, {ID_HR, HRAlign, T_String, ATTR_ALIGN}, {ID_HR, HRNoShade, T_Bool, ATTR_NOSHADE}, {ID_HR, HRSize, T_String, ATTR_SIZE}, {ID_HR, HRWidth, T_String, ATTR_WIDTH}, {NotApplicable, ModCite, T_String, ATTR_CITE}, {NotApplicable, ModDateTime, T_String, ATTR_DATETIME}, {ID_A, AnchorAccessKey, T_String, ATTR_ACCESSKEY}, {ID_A, AnchorCharset, T_String, ATTR_CHARSET}, {ID_A, AnchorCoords, T_String, ATTR_COORDS}, {ID_A, AnchorHref, T_URL, ATTR_HREF}, {ID_A, AnchorHrefLang, T_String, ATTR_HREFLANG}, {ID_A, AnchorName, T_String, ATTR_NAME}, {ID_A, AnchorRel, T_String, ATTR_REL}, {ID_A, AnchorRev, T_String, ATTR_REV}, {ID_A, AnchorShape, T_String, ATTR_SHAPE}, {ID_A, AnchorTabIndex, T_Int, ATTR_TABINDEX}, //### not ->tabIndex?? {ID_A, AnchorTarget, T_String, ATTR_TARGET}, {ID_A, AnchorType, T_String, ATTR_TYPE}, {ID_IMG, ImageName, T_String, ATTR_NAME}, {ID_IMG, ImageAlign, T_String, ATTR_ALIGN}, {ID_IMG, ImageAlt, T_String, ATTR_ALT}, {ID_IMG, ImageBorder, T_String, ATTR_BORDER}, {ID_IMG, ImageHspace, T_Int, ATTR_HSPACE}, // ### return actual value {ID_IMG, ImageIsMap, T_Bool, ATTR_ISMAP}, {ID_IMG, ImageLongDesc, T_String, ATTR_LONGDESC}, {ID_IMG, ImageSrc, T_URL, ATTR_SRC}, {ID_IMG, ImageUseMap, T_String, ATTR_USEMAP}, {ID_IMG, ImageVspace, T_Int, ATTR_VSPACE}, // ### return actual value {ID_OBJECT, ObjectCode, T_String, ATTR_CODE}, {ID_OBJECT, ObjectAlign, T_String, ATTR_ALIGN}, {ID_OBJECT, ObjectArchive, T_String, ATTR_ARCHIVE}, {ID_OBJECT, ObjectBorder, T_String, ATTR_BORDER}, {ID_OBJECT, ObjectCodeBase, T_String, ATTR_CODEBASE}, {ID_OBJECT, ObjectCodeType, T_String, ATTR_CODETYPE}, {ID_OBJECT, ObjectData, T_URL, ATTR_DATA}, {ID_OBJECT, ObjectDeclare, T_Bool, ATTR_DECLARE}, {ID_OBJECT, ObjectHeight, T_String, ATTR_HEIGHT}, {ID_OBJECT, ObjectHspace, T_Int, ATTR_HSPACE}, {ID_OBJECT, ObjectName, T_String, ATTR_NAME}, {ID_OBJECT, ObjectStandby, T_String, ATTR_STANDBY}, {ID_OBJECT, ObjectTabIndex, T_Int, ATTR_TABINDEX}, //### not element's tabindex? {ID_OBJECT, ObjectType, T_String, ATTR_TYPE}, {ID_OBJECT, ObjectUseMap, T_String, ATTR_USEMAP}, {ID_OBJECT, ObjectVspace, T_Int, ATTR_VSPACE}, {ID_OBJECT, ObjectWidth, T_String, ATTR_WIDTH}, {ID_PARAM, ParamName, T_String, ATTR_NAME}, {ID_PARAM, ParamType, T_String, ATTR_TYPE}, {ID_PARAM, ParamValue, T_String, ATTR_VALUE}, {ID_PARAM, ParamValueType, T_String, ATTR_VALUETYPE}, {ID_APPLET, AppletAlign, T_String, ATTR_ALIGN}, {ID_APPLET, AppletAlt, T_String, ATTR_ALT}, {ID_APPLET, AppletArchive, T_String, ATTR_ARCHIVE}, {ID_APPLET, AppletCode, T_String, ATTR_CODE}, {ID_APPLET, AppletCodeBase, T_String, ATTR_CODEBASE}, {ID_APPLET, AppletHeight, T_String, ATTR_HEIGHT}, {ID_APPLET, AppletHspace, T_Int, ATTR_HSPACE}, {ID_APPLET, AppletName, T_String, ATTR_NAME}, {ID_APPLET, AppletObject, T_String, ATTR_OBJECT}, {ID_APPLET, AppletVspace, T_Int, ATTR_VSPACE}, {ID_APPLET, AppletWidth, T_String, ATTR_WIDTH}, {ID_MAP, MapName, T_String, ATTR_NAME}, {ID_MAP, MapAreas, T_Coll, HTMLCollectionImpl::MAP_AREAS}, {ID_AREA, AreaAccessKey, T_String, ATTR_ACCESSKEY}, {ID_AREA, AreaAlt, T_String, ATTR_ALT}, {ID_AREA, AreaCoords, T_String, ATTR_COORDS}, {ID_AREA, AreaHref, T_URL, ATTR_HREF}, {ID_AREA, AreaNoHref, T_Bool, ATTR_NOHREF}, {ID_AREA, AreaShape, T_String, ATTR_SHAPE}, {ID_AREA, AreaTabIndex, T_Int, ATTR_TABINDEX}, {ID_AREA, AreaTarget, T_String, ATTR_TARGET}, {ID_SCRIPT, ScriptHtmlFor, T_Res, NotApplicable}, {ID_SCRIPT, ScriptEvent, T_Res, NotApplicable}, {ID_SCRIPT, ScriptCharset, T_String, ATTR_CHARSET}, {ID_SCRIPT, ScriptDefer, T_Bool, ATTR_DEFER}, {ID_SCRIPT, ScriptSrc, T_URL, ATTR_SRC}, {ID_SCRIPT, ScriptType, T_String, ATTR_TYPE}, {ID_TABLE, TableAlign, T_String, ATTR_ALIGN}, {ID_TABLE, TableBgColor, T_String, ATTR_BGCOLOR}, {ID_TABLE, TableBorder, T_String, ATTR_BORDER}, {ID_TABLE, TableCellPadding, T_String, ATTR_CELLPADDING}, {ID_TABLE, TableCellSpacing, T_String, ATTR_CELLSPACING}, {ID_TABLE, TableFrame, T_String, ATTR_FRAME}, {ID_TABLE, TableRules, T_String, ATTR_RULES}, {ID_TABLE, TableSummary, T_String, ATTR_SUMMARY}, {ID_TABLE, TableWidth, T_String, ATTR_WIDTH}, {ID_TABLE, TableRows, T_Coll, HTMLCollectionImpl::TABLE_ROWS}, {ID_TABLE, TableTBodies, T_Coll, HTMLCollectionImpl::TABLE_TBODIES}, {ID_CAPTION, TableCaptionAlign,T_String, ATTR_ALIGN}, {NotApplicable,TableColAlign, T_String, ATTR_ALIGN}, //Col/ColGroup {NotApplicable,TableColCh, T_String, ATTR_CHAR}, {NotApplicable,TableColChOff, T_String, ATTR_CHAROFF}, {NotApplicable,TableColSpan, T_Int, ATTR_SPAN}, {NotApplicable,TableColVAlign, T_String, ATTR_VALIGN}, {NotApplicable,TableColWidth, T_String, ATTR_WIDTH}, {NotApplicable,TableSectionAlign,T_String, ATTR_ALIGN}, //THead/TBody/TFoot {NotApplicable,TableSectionCh, T_String, ATTR_CHAR}, {NotApplicable,TableSectionChOff,T_String, ATTR_CHAROFF}, {NotApplicable,TableSectionVAlign,T_String, ATTR_VALIGN}, {NotApplicable,TableSectionRows, T_Coll, HTMLCollectionImpl::TSECTION_ROWS}, {ID_TR, TableRowAlign, T_String, ATTR_ALIGN}, //TR {ID_TR, TableRowBgColor, T_String, ATTR_BGCOLOR}, {ID_TR, TableRowCh, T_String, ATTR_CHAR}, {ID_TR, TableRowChOff, T_String, ATTR_CHAROFF}, {ID_TR, TableRowVAlign, T_String, ATTR_VALIGN}, {ID_TR, TableRowCells, T_Coll, HTMLCollectionImpl::TR_CELLS}, {NotApplicable,TableCellAbbr, T_String, ATTR_ABBR}, //TD/TH {NotApplicable,TableCellAlign, T_String, ATTR_ALIGN}, {NotApplicable,TableCellAxis, T_String, ATTR_AXIS}, {NotApplicable,TableCellBgColor, T_String, ATTR_BGCOLOR}, {NotApplicable,TableCellCh, T_String, ATTR_CHAR}, {NotApplicable,TableCellChOff, T_String, ATTR_CHAROFF}, {NotApplicable,TableCellColSpan, T_Int, ATTR_COLSPAN}, {NotApplicable,TableCellHeaders, T_String, ATTR_HEADERS}, {NotApplicable,TableCellHeight, T_String, ATTR_HEIGHT}, {NotApplicable,TableCellNoWrap, T_Bool, ATTR_NOWRAP}, {NotApplicable,TableCellRowSpan, T_Int, ATTR_ROWSPAN}, {NotApplicable,TableCellScope, T_String, ATTR_SCOPE}, {NotApplicable,TableCellVAlign, T_String, ATTR_VALIGN}, {NotApplicable,TableCellWidth, T_String, ATTR_WIDTH}, {ID_FRAMESET, FrameSetCols, T_String, ATTR_COLS}, {ID_FRAMESET, FrameSetRows, T_String, ATTR_ROWS}, {ID_LAYER, LayerTop, T_Int, ATTR_TOP}, {ID_LAYER, LayerLeft, T_Int, ATTR_LEFT}, {ID_LAYER, LayerVisibility, T_StrOrNl,ATTR_VISIBILITY}, {ID_LAYER, LayerBgColor, T_StrOrNl,ATTR_BGCOLOR}, {ID_LAYER, LayerLayers, T_Coll, HTMLCollectionImpl::DOC_LAYERS}, {ID_FRAME, FrameFrameBorder, T_String, ATTR_FRAMEBORDER}, {ID_FRAME, FrameLongDesc, T_String, ATTR_LONGDESC}, {ID_FRAME, FrameMarginHeight, T_String, ATTR_MARGINHEIGHT}, {ID_FRAME, FrameMarginWidth, T_String, ATTR_MARGINWIDTH}, {ID_FRAME, FrameName, T_String, ATTR_NAME}, {ID_FRAME, FrameNoResize, T_Bool, ATTR_NORESIZE}, {ID_FRAME, FrameScrolling, T_String, ATTR_SCROLLING}, {ID_FRAME, FrameSrc, T_String, ATTR_SRC}, //### not URL? {ID_FRAME, FrameLocation, BoundPropType(T_String | T_ReadOnly), ATTR_SRC}, {ID_IFRAME, IFrameFrameBorder, T_String, ATTR_FRAMEBORDER}, {ID_IFRAME, IFrameLongDesc, T_String, ATTR_LONGDESC}, {ID_IFRAME, IFrameMarginHeight,T_String, ATTR_MARGINHEIGHT}, {ID_IFRAME, IFrameMarginWidth, T_String, ATTR_MARGINWIDTH}, {ID_IFRAME, IFrameName, T_String, ATTR_NAME}, {ID_IFRAME, IFrameScrolling, T_String, ATTR_SCROLLING}, {ID_IFRAME, IFrameSrc, T_URL, ATTR_SRC}, {ID_IFRAME, IFrameAlign, T_String, ATTR_ALIGN}, {ID_IFRAME, IFrameHeight, T_String, ATTR_HEIGHT}, {ID_IFRAME, IFrameWidth, T_String, ATTR_WIDTH}, {NotApplicable,ElementId, T_String, ATTR_ID}, {NotApplicable,ElementTitle, T_String, ATTR_TITLE}, {NotApplicable,ElementLang, T_String, ATTR_LANG}, {NotApplicable,ElementDir, T_String, ATTR_DIR}, {NotApplicable,ElementClassName, T_String, ATTR_CLASS}, {NotApplicable,ElementChildren, T_Coll, HTMLCollectionImpl::NODE_CHILDREN}, {0, 0, T_Res, 0}, }; QHash* HTMLElement::s_boundPropInfo = 0; QHash* HTMLElement::boundPropInfo() { if (!s_boundPropInfo) { s_boundPropInfo = new QHash(); for (int c = 0; bpTable[c].elId; ++c) { s_boundPropInfo->insert(bpTable[c].token, &bpTable[c]); } } return s_boundPropInfo; } QString KJS::HTMLElement::getURLArg(unsigned id) const { DOMString rel = impl()->getAttribute(id); return !rel.isNull() ? impl()->getDocument()->completeURL(rel.string()) : QString(); } DOM::HTMLElementImpl *toHTMLElement(JSValue *val) { DOM::ElementImpl* e = toElement(val); if (e && e->isHTMLElement()) return static_cast(e); return 0; } DOM::HTMLTableCaptionElementImpl *toHTMLTableCaptionElement(JSValue *val) { DOM::ElementImpl *e = toElement(val); if (e && e->id() == ID_CAPTION) return static_cast(e); return 0; } HTMLTableSectionElementImpl *toHTMLTableSectionElement(JSValue *val) { DOM::ElementImpl *e = toElement(val); if (e && (e->id() == ID_THEAD || e->id() == ID_TBODY || e->id() == ID_TFOOT)) return static_cast(e); return 0; } JSValue* KJS::HTMLElement::handleBoundRead(ExecState* exec, int token) const { const BoundPropInfo* prop = boundPropInfo()->value(token); if (!prop) return 0; assert(prop->elId == NotApplicable || prop->elId == impl()->id()); switch (prop->type & ~T_ReadOnly) { case T_String: return jsString(impl()->getAttribute(prop->attrId)); case T_StrOrNl: return getStringOrNull(impl()->getAttribute(prop->attrId)); case T_Bool: return jsBoolean(!impl()->getAttribute(prop->attrId).isNull()); case T_Int: return jsNumber(impl()->getAttribute(prop->attrId).toInt()); case T_URL: return jsString(getURLArg(prop->attrId)); case T_TabIdx: return jsNumber(impl()->tabIndex()); case T_Res: return jsString(""); case T_Coll: return getHTMLCollection(exec, new HTMLCollectionImpl(impl(), prop->attrId)); } assert(0); return 0; } JSValue* KJS::HTMLElement::getValueProperty(ExecState *exec, int token) const { JSValue* cand = handleBoundRead(exec, token); if (cand) return cand; DOM::HTMLElementImpl& element = *impl(); switch (element.id()) { case ID_LINK: { DOM::HTMLLinkElementImpl& link = static_cast(element); switch (token) { case LinkSheet: return getDOMStyleSheet(exec,link.sheet()); } } break; case ID_TITLE: { DOM::HTMLTitleElementImpl& title = static_cast(element); switch (token) { case TitleText: return jsString(title.text()); } } break; case ID_ISINDEX: { DOM::HTMLIsIndexElementImpl& isindex = static_cast(element); switch (token) { case IsIndexForm: return getDOMNode(exec,isindex.form()); // type HTMLFormElement case IsIndexPrompt: return jsString(isindex.prompt()); } } break; case ID_STYLE: { DOM::HTMLStyleElementImpl& style = static_cast(element); switch (token) { case StyleSheet: return getDOMStyleSheet(exec,style.sheet()); } } break; case ID_BODY: { switch (token) { case BodyOnLoad: { DOM::DocumentImpl *doc = impl()->getDocument(); if (!doc || !checkNodeSecurity(exec, impl())) return jsUndefined(); DOMNode* kjsDocNode = new DOMNode(exec, doc); // Need to create a Value wrapper to avoid leaking the KJS::DOMNode //Value nodeValue(kjsDocNode); return kjsDocNode->getListener( DOM::EventImpl::LOAD_EVENT ); } } } break; case ID_FORM: { DOM::HTMLFormElementImpl& form = static_cast(element); switch (token) { case FormElements: return getHTMLCollection(exec,form.elements()); case FormLength: return jsNumber(form.length()); } } break; case ID_SELECT: { DOM::HTMLSelectElementImpl& select = static_cast(element); switch (token) { case SelectType: return jsString(select.type()); case SelectSelectedIndex: return jsNumber(select.selectedIndex()); case SelectValue: return jsString(select.value()); case SelectLength: return jsNumber(select.length()); case SelectForm: return getDOMNode(exec,select.form()); // type HTMLFormElement case SelectOptions: return getSelectHTMLCollection(exec, select.options(), &select); // type HTMLCollection case SelectName: return jsString(select.name()); } } break; case ID_OPTION: { DOM::HTMLOptionElementImpl& option = static_cast(element); switch (token) { case OptionForm: return getDOMNode(exec,option.form()); // type HTMLFormElement case OptionText: return jsString(option.text()); case OptionIndex: return jsNumber(option.index()); case OptionSelected: return jsBoolean(option.selected()); case OptionValue: return jsString(option.value()); } } break; case ID_INPUT: { DOM::HTMLInputElementImpl& input = static_cast(element); switch (token) { case InputForm: return getDOMNode(exec,input.form()); // type HTMLFormElement case InputChecked: return jsBoolean(input.checked()); case InputIndeterminate: return jsBoolean(input.indeterminate()); case InputName: return jsString(input.name()); // NOT getString (IE gives empty string) case InputType: return jsString(input.type()); case InputValue: return jsString(input.value()); case InputSelectionStart: { long val = input.selectionStart(); if (val != -1) return jsNumber(val); else return jsUndefined(); } case InputSelectionEnd: { long val = input.selectionEnd(); if (val != -1) return jsNumber(val); else return jsUndefined(); } } } break; case ID_TEXTAREA: { DOM::HTMLTextAreaElementImpl& textarea = static_cast(element); switch (token) { case TextAreaDefaultValue: return jsString(textarea.defaultValue()); case TextAreaForm: return getDOMNode(exec,textarea.form()); // type HTMLFormElement case TextAreaName: return jsString(textarea.name()); case TextAreaType: return jsString(textarea.type()); case TextAreaValue: return jsString(textarea.value()); case TextAreaSelectionStart: return jsNumber(textarea.selectionStart()); case TextAreaSelectionEnd: return jsNumber(textarea.selectionEnd()); case TextAreaTextLength: return jsNumber(textarea.textLength()); } } break; case ID_BUTTON: { DOM::HTMLButtonElementImpl& button = static_cast(element); switch (token) { case ButtonForm: return getDOMNode(exec,button.form()); // type HTMLFormElement case ButtonType: return jsString(button.type()); } } break; case ID_LABEL: { DOM::HTMLLabelElementImpl& label = static_cast(element); switch (token) { case LabelForm: return getDOMNode(exec,label.form()); // type HTMLFormElement } } break; case ID_FIELDSET: { DOM::HTMLFieldSetElementImpl& fieldSet = static_cast(element); switch (token) { case FieldSetForm: return getDOMNode(exec,fieldSet.form()); // type HTMLFormElement } } break; case ID_LEGEND: { DOM::HTMLLegendElementImpl& legend = static_cast(element); switch (token) { case LegendForm: return getDOMNode(exec,legend.form()); // type HTMLFormElement } } break; case ID_A: { DOM::HTMLAnchorElementImpl& anchor = static_cast(element); QString href = getURLArg(ATTR_HREF); switch (token) { case AnchorHash: return jsString('#'+KUrl(href).ref()); case AnchorHost: return jsString(KUrl(href).host()); case AnchorHostname: { KUrl url(href); kDebug(6070) << "anchor::hostname uses:" <(element); switch (token) { case ImageComplete: return jsBoolean(image.complete()); case ImageHeight: return jsNumber(image.height()); case ImageWidth: return jsNumber(image.width()); case ImageX: return jsNumber(image.x()); case ImageY: return jsNumber(image.y()); } } break; case ID_CANVAS: { DOM::HTMLCanvasElementImpl& canvas = static_cast(element); switch (token) { case CanvasHeight: return jsNumber(canvas.height()); case CanvasWidth: return jsNumber(canvas.width()); } } break; case ID_OBJECT: { DOM::HTMLObjectElementImpl& object = static_cast(element); switch (token) { case ObjectForm: return getDOMNode(exec,object.form()); // type HTMLFormElement case ObjectContentDocument: return checkNodeSecurity(exec,object.contentDocument()) ? getDOMNode(exec, object.contentDocument()) : jsUndefined(); } } break; case ID_AREA: { DOM::HTMLAreaElementImpl& area = static_cast(element); // Everything here needs href DOM::Document doc = area.ownerDocument(); DOM::DOMString href = getURLArg(ATTR_HREF); KUrl url; if ( !href.isNull() ) { url = href.string(); if ( href.isEmpty() ) url.setFileName( QString() ); // href="" clears the filename (in IE) } switch(token) { case AreaHref: return jsString(url.url()); case AreaHash: return jsString(url.isEmpty() ? "" : '#'+url.ref()); case AreaHost: return jsString(url.host()); case AreaHostName: { if (url.port()<=0) return jsString(url.host()); else return jsString(url.host() + ":" + QString::number(url.port())); } case AreaPathName: { return jsString(url.path()); } case AreaPort: return jsString(QString::number(url.port())); case AreaProtocol: return jsString(url.isEmpty() ? "" : url.protocol()+":"); case AreaSearch: return jsString(url.query()); } } break; case ID_SCRIPT: { DOM::HTMLScriptElementImpl& script = static_cast(element); switch (token) { case ScriptText: return jsString(script.text()); } } break; case ID_TABLE: { DOM::HTMLTableElementImpl& table = static_cast(element); switch (token) { case TableCaption: return getDOMNode(exec,table.caption()); // type HTMLTableCaptionElement case TableTHead: return getDOMNode(exec,table.tHead()); // type HTMLTableSectionElement case TableTFoot: return getDOMNode(exec,table.tFoot()); // type HTMLTableSectionElement } } break; case ID_TR: { DOM::HTMLTableRowElementImpl& tableRow = static_cast(element); switch (token) { case TableRowRowIndex: return jsNumber(tableRow.rowIndex()); case TableRowSectionRowIndex: return jsNumber(tableRow.sectionRowIndex()); } } break; case ID_TH: case ID_TD: { DOM::HTMLTableCellElementImpl& tableCell = static_cast(element); switch (token) { case TableCellCellIndex: return jsNumber(tableCell.cellIndex()); } } break; case ID_LAYER: { DOM::HTMLLayerElementImpl& layerElement = static_cast(element); switch (token) { /*case LayerClip: return getLayerClip(exec, layerElement); */ case LayerDocument: return jsUndefined(); } } break; case ID_FRAME: { DOM::HTMLFrameElementImpl& frameElement = static_cast(element); switch (token) { case FrameContentDocument: return checkNodeSecurity(exec,frameElement.contentDocument()) ? getDOMNode(exec, frameElement.contentDocument()) : jsUndefined(); case FrameContentWindow: { KHTMLPart* part = frameElement.contentPart(); if (part) { Window *w = Window::retrieveWindow(part); if (w) return w; } return jsUndefined(); } // IE only case FrameWidth: case FrameHeight: { frameElement.getDocument()->updateLayout(); khtml::RenderObject* r = frameElement.renderer(); return jsNumber( r ? (token == FrameWidth ? r->width() : r->height()) : 0 ); } } } break; case ID_IFRAME: { DOM::HTMLIFrameElementImpl& iFrame = static_cast(element); switch (token) { case IFrameContentDocument: return checkNodeSecurity(exec,iFrame.contentDocument()) ? getDOMNode(exec, iFrame.contentDocument()) : jsUndefined(); case IFrameContentWindow: { KHTMLPart* part = iFrame.contentPart(); if (part) { Window *w = Window::retrieveWindow(part); if (w) return w; } return jsUndefined(); } } break; } } // xemacs (or arnt) could be a bit smarter when it comes to indenting switch()es ;) // its not arnt to blame - its the original Stroustrup style we like :) (Dirk) // generic properties switch (token) { case ElementInnerHTML: return jsString(element.innerHTML()); case ElementInnerText: return jsString(element.innerText()); case ElementDocument: return getDOMNode(exec,element.ownerDocument()); case ElementAll: // Disable element.all when we try to be Netscape-compatible if ( exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat ) return jsUndefined(); else if ( exec->dynamicInterpreter()->compatMode() == Interpreter::IECompat ) return getHTMLCollection(exec,new HTMLCollectionImpl(&element, HTMLCollectionImpl::DOC_ALL)); else // Enabled but hidden by default return getHTMLCollection(exec,new HTMLCollectionImpl(&element, HTMLCollectionImpl::DOC_ALL), true); // ### what about style? or is this used instead for DOM2 stylesheets? } kError() << "HTMLElement::getValueProperty unhandled token " << token << endl; return jsUndefined(); } UString KJS::HTMLElement::toString(ExecState *exec) const { if (impl()->id() == ID_A) return UString(getURLArg(ATTR_HREF)); else if (impl()->id() == ID_APPLET) { KParts::LiveConnectExtension *lc = getLiveConnectExtension(*impl()); QStringList qargs; QString retvalue; KParts::LiveConnectExtension::Type rettype; unsigned long retobjid; if (lc && lc->call(0, "hashCode", qargs, rettype, retobjid, retvalue)) { QString str("[object APPLET ref="); return UString(str + retvalue + QString("]")); } } else if (impl()->id() == ID_IMG) { DOMString alt = impl()->getAttribute(ATTR_ALT); if (!alt.isEmpty()) return UString(alt) + " " + DOMElement::toString(exec); } return DOMElement::toString(exec); } static DOM::HTMLFormElementImpl* getForm(const DOM::HTMLElementImpl* element) { switch (element->id()) { case ID_ISINDEX: case ID_SELECT: case ID_OPTION: case ID_INPUT: case ID_TEXTAREA: case ID_LABEL: case ID_FIELDSET: case ID_LEGEND: { const DOM::HTMLGenericFormElementImpl* fEl = static_cast(element); return fEl->form(); } case ID_OBJECT: { const DOM::HTMLObjectElementImpl* oEl = static_cast(element); return oEl->form(); } default: return 0; } } void KJS::HTMLElement::pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const { DOM::HTMLElementImpl& element = *impl(); // The document is put on first, fall back to searching it only after the element and form. scope.push(static_cast(getDOMNode(exec, element.getDocument()))); // The form is next, searched before the document, but after the element itself. DOM::HTMLFormElementImpl* formElt; // First try to obtain the form from the element itself. We do this to deal with // the malformed case where
s aren't in our parent chain (e.g., when they were inside // or . formElt = getForm(impl()); if (formElt) scope.push(static_cast(getDOMNode(exec, formElt))); else { DOM::NodeImpl* form = element.parentNode(); while (form && form->id() != ID_FORM) form = form->parentNode(); if (form) scope.push(static_cast(getDOMNode(exec, form))); } // The element is on top, searched first. scope.push(static_cast(getDOMNode(exec, &element))); } JSValue* KJS::HTMLElementFunction::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { KJS_CHECK_THIS( HTMLElement, thisObj ); DOMExceptionTranslator exception(exec); #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLElementFunction::callAsFunction "; #endif DOM::HTMLElementImpl& element = *static_cast(thisObj)->impl(); switch (element.id()) { case ID_FORM: { DOM::HTMLFormElementImpl& form = static_cast(element); if (id == KJS::HTMLElement::FormSubmit) { KHTMLView *view = element.getDocument()->view(); KHTMLSettings::KJSWindowOpenPolicy policy = KHTMLSettings::KJSWindowOpenAllow; if (view) policy = view->part()->settings()->windowOpenPolicy(view->part()->url().host()); bool block = false; if ( policy != KHTMLSettings::KJSWindowOpenAllow ) { block = true; // if this is a form without a target, or a special target, don't block QString trg = form.target().lower().string(); if( trg.isEmpty() || trg == "_top" || trg == "_self" || trg == "_parent") block = false; QString caption; // if there is a frame with the target name, don't block if ( view && view->part() ) { if (!view->part()->url().host().isEmpty()) caption = view->part()->url().host() + " - "; // search all (possibly nested) framesets KHTMLPart *currentPart = view->part()->parentPart(); while( currentPart != 0L ) { if( currentPart->frameExists( form.target().string() ) ) block = false; currentPart = currentPart->parentPart(); } } if ( block && policy == KHTMLSettings::KJSWindowOpenAsk && view ) { if (view && view->part()) emit view->part()->browserExtension()->requestFocus(view->part()); caption += i18n( "Confirmation: JavaScript Popup" ); if ( KMessageBox::questionYesNo(view, form.action().isEmpty() ? i18n( "This site is submitting a form which will open up a new browser " "window via JavaScript.\n" "Do you want to allow the form to be submitted?" ) : i18n( "This site is submitting a form which will open

%1

in a new browser window via JavaScript.
" "Do you want to allow the form to be submitted?
", KStringHandler::csqueeze(form.action().string(), 100)), caption, KGuiItem(i18n("Allow")), KGuiItem(i18n("Do Not Allow")) ) == KMessageBox::Yes ) block = false; } else if ( block && policy == KHTMLSettings::KJSWindowOpenSmart ) { if( static_cast(exec->dynamicInterpreter())->isWindowOpenAllowed() ) { // This submission has been triggered by the user block = false; } } } if( !block ) form.submit(); return jsUndefined(); } else if (id == KJS::HTMLElement::FormReset) { form.reset(); return jsUndefined(); } } break; case ID_SELECT: { DOM::HTMLSelectElementImpl& select = static_cast(element); if (id == KJS::HTMLElement::SelectAdd) { select.add(toHTMLElement(args[0]),toHTMLElement(args[1]),exception); return jsUndefined(); } else if (id == KJS::HTMLElement::SelectRemove) { select.remove(int(args[0]->toNumber(exec))); return jsUndefined(); } else if (id == KJS::HTMLElement::SelectBlur) { select.blur(); return jsUndefined(); } else if (id == KJS::HTMLElement::SelectFocus) { select.focus(); return jsUndefined(); } } break; case ID_INPUT: { DOM::HTMLInputElementImpl& input = static_cast(element); if (id == KJS::HTMLElement::InputBlur) { input.blur(); return jsUndefined(); } else if (id == KJS::HTMLElement::InputFocus) { input.focus(); return jsUndefined(); } else if (id == KJS::HTMLElement::InputSelect) { input.select(); return jsUndefined(); } else if (id == KJS::HTMLElement::InputClick) { input.click(); return jsUndefined(); } else if (id == KJS::HTMLElement::InputSetSelectionRange) { input.setSelectionRange(args[0]->toNumber(exec), args[1]->toNumber(exec)); return jsUndefined(); } } break; case ID_BUTTON: { DOM::HTMLButtonElementImpl& button = static_cast(element); if (id == KJS::HTMLElement::ButtonBlur) { button.blur(); return jsUndefined(); } else if (id == KJS::HTMLElement::ButtonFocus) { button.focus(); return jsUndefined(); } } break; case ID_TEXTAREA: { DOM::HTMLTextAreaElementImpl& textarea = static_cast(element); if (id == KJS::HTMLElement::TextAreaBlur) { textarea.blur(); return jsUndefined(); } else if (id == KJS::HTMLElement::TextAreaFocus) { textarea.focus(); return jsUndefined(); } else if (id == KJS::HTMLElement::TextAreaSelect) { textarea.select(); return jsUndefined(); } else if (id == KJS::HTMLElement::TextAreaSetSelectionRange) { textarea.setSelectionRange(args[0]->toNumber(exec), args[1]->toNumber(exec)); return jsUndefined(); } } break; case ID_A: { DOM::HTMLAnchorElementImpl& anchor = static_cast(element); if (id == KJS::HTMLElement::AnchorBlur) { anchor.blur(); return jsUndefined(); } else if (id == KJS::HTMLElement::AnchorFocus) { anchor.focus(); return jsUndefined(); } else if (id == KJS::HTMLElement::AnchorClick) { anchor.click(); return jsUndefined(); } } break; case ID_TABLE: { DOM::HTMLTableElementImpl& table = static_cast(element); if (id == KJS::HTMLElement::TableCreateTHead) return getDOMNode(exec,table.createTHead()); else if (id == KJS::HTMLElement::TableDeleteTHead) { table.deleteTHead(); return jsUndefined(); } else if (id == KJS::HTMLElement::TableCreateTFoot) return getDOMNode(exec,table.createTFoot()); else if (id == KJS::HTMLElement::TableDeleteTFoot) { table.deleteTFoot(); return jsUndefined(); } else if (id == KJS::HTMLElement::TableCreateCaption) return getDOMNode(exec,table.createCaption()); else if (id == KJS::HTMLElement::TableDeleteCaption) { table.deleteCaption(); return jsUndefined(); } else if (id == KJS::HTMLElement::TableInsertRow) return getDOMNode(exec,table.insertRow(args[0]->toInteger(exec),exception)); else if (id == KJS::HTMLElement::TableDeleteRow) { table.deleteRow(args[0]->toInteger(exec), exception); return jsUndefined(); } } break; case ID_THEAD: case ID_TBODY: case ID_TFOOT: { DOM::HTMLTableSectionElementImpl& tableSection = static_cast(element); if (id == KJS::HTMLElement::TableSectionInsertRow) return getDOMNode(exec,tableSection.insertRow(args[0]->toInteger(exec), exception)); else if (id == KJS::HTMLElement::TableSectionDeleteRow) { tableSection.deleteRow(args[0]->toInteger(exec),exception); return jsUndefined(); } } break; case ID_TR: { DOM::HTMLTableRowElementImpl& tableRow = static_cast(element); if (id == KJS::HTMLElement::TableRowInsertCell) return getDOMNode(exec,tableRow.insertCell(args[0]->toInteger(exec), exception)); else if (id == KJS::HTMLElement::TableRowDeleteCell) { tableRow.deleteCell(args[0]->toInteger(exec), exception); return jsUndefined(); } break; } case ID_MARQUEE: { if (id == KJS::HTMLElement::MarqueeStart && element.renderer() && element.renderer()->layer() && element.renderer()->layer()->marquee()) { element.renderer()->layer()->marquee()->start(); return jsUndefined(); } else if (id == KJS::HTMLElement::MarqueeStop && element.renderer() && element.renderer()->layer() && element.renderer()->layer()->marquee()) { element.renderer()->layer()->marquee()->stop(); return jsUndefined(); } break; } case ID_CANVAS: { DOM::HTMLCanvasElementImpl& canvasEl = static_cast(element); if (id == KJS::HTMLElement::CanvasGetContext) { if (args[0]->toString(exec) == "2d") return getWrapper(exec, canvasEl.getContext2D()); return jsNull(); } else if (id == KJS::HTMLElement::CanvasToDataURL) { return jsString(canvasEl.toDataURL(exception)); } break; } } if (id == HTMLElement::ElementScrollIntoView) { bool alignToTop = true; if (args.size() > 0) alignToTop = args[0]->toBoolean(exec); element.scrollIntoView(alignToTop); return jsUndefined(); } return jsUndefined(); } void KJS::HTMLElement::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) { #ifdef KJS_VERBOSE DOM::DOMString str = value->type() == NullType ? DOM::DOMString() : value->toString(exec).domString(); #endif DOM::HTMLElementImpl& element = *impl(); #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLElement::tryPut " << propertyName.qstring() << " thisTag=" << element.tagName().string() << " str=" << str.string() << endl; #endif // // First look at dynamic properties switch (element.id()) { case ID_SELECT: { DOM::HTMLSelectElementImpl& select = static_cast(element); bool ok; /*uint u =*/ propertyName.qstring().toULong(&ok); if (ok) { JSObject *coll = getSelectHTMLCollection(exec, select.options(), &select)->getObject(); if ( coll ) coll->put(exec,propertyName,value); return; } break; } case ID_APPLET: case ID_OBJECT: case ID_EMBED: { KParts::LiveConnectExtension *lc = getLiveConnectExtension(element); if (lc && lc->put(0, propertyName.qstring(), value->toString(exec).qstring())) return; break; } default: break; } const HashTable* table = classInfo()->propHashTable; // get the right hashtable const HashEntry* entry = table ? Lookup::findEntry(table, propertyName) : 0; if (entry) { if (entry->attr & Function) { // function: put as override property JSObject::put(exec, propertyName, value, attr); return; } else if (!(entry->attr & ReadOnly)) { // let lookupPut print the warning if read-only putValueProperty(exec, entry->value, value, attr); return; } } lookupPut(exec, propertyName, value, attr, &HTMLElementTable, this); } bool KJS::HTMLElement::handleBoundWrite(ExecState* exec, int token, JSValue* value) { const BoundPropInfo* prop = boundPropInfo()->value(token); if (!prop) return false; if (prop->type & T_ReadOnly) return false; DOM::DOMString str = value->type() == NullType ? DOM::DOMString() : value->toString(exec).domString(); assert(prop->elId == NotApplicable || prop->elId == impl()->id()); switch (prop->type) { case T_String: case T_StrOrNl: case T_URL: impl()->setAttribute(prop->attrId, str); return true; case T_Int: impl()->setAttribute(prop->attrId, QString::number(value->toInteger(exec))); return true; case T_Bool: impl()->setAttribute(prop->attrId, value->toBoolean(exec) ? "" : 0); return true; case T_TabIdx: impl()->setTabIndex(value->toInteger(exec)); return true; case T_Res: //ignored return true; } assert(0); return false; } void KJS::HTMLElement::putValueProperty(ExecState *exec, int token, JSValue *value, int) { if (handleBoundWrite(exec, token, value)) return; DOMExceptionTranslator exception(exec); DOM::DOMString str = value->type() == NullType ? DOM::DOMString() : value->toString(exec).domString(); DOM::HTMLElementImpl& element = *impl(); #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLElement::putValueProperty " << " thisTag=" << element.tagName().string() << " token=" << token << endl; #endif switch (element.id()) { case ID_TITLE: { DOM::HTMLTitleElementImpl& title = static_cast(element); switch (token) { case TitleText: { title.setText(str); return; } } } break; case ID_ISINDEX: { DOM::HTMLIsIndexElementImpl& isindex = static_cast(element); switch (token) { // read-only: form case IsIndexPrompt: { isindex.setPrompt(str); return; } } } break; case ID_BODY: { DOM::HTMLBodyElementImpl& body = static_cast(element); switch (token) { case BodyOnLoad: DOM::DocumentImpl *doc = element.getDocument(); if (doc && checkNodeSecurity(exec, impl())) { DOMNode* kjsDocNode = new DOMNode(exec, doc); // Need to create a Value wrapper to avoid leaking the KJS::DOMNode //Value nodeValue(kjsDocNode); kjsDocNode->setListener(exec,DOM::EventImpl::LOAD_EVENT,value); } return; } } break; case ID_SELECT: { DOM::HTMLSelectElementImpl& select = static_cast(element); switch (token) { // read-only: type case SelectSelectedIndex: { select.setSelectedIndex(value->toInteger(exec)); return; } case SelectValue: { select.setValue(str.implementation()); return; } case SelectLength: { // read-only according to the NS spec, but webpages need it writeable JSObject *coll = getSelectHTMLCollection(exec, select.options(), &select)->getObject(); if ( coll ) coll->put(exec,"length",value); return; } // read-only: form // read-only: options case SelectName: { select.setName(str); return; } } } break; case ID_OPTION: { DOM::HTMLOptionElementImpl& option = static_cast(element); switch (token) { // read-only: form // read-only: text <--- According to the DOM, but JavaScript and JScript both allow changes. // So, we'll do it here and not add it to our DOM headers. case OptionText: { SharedPtr nl(option.childNodes()); for (unsigned int i = 0; i < nl->length(); i++) { if (nl->item(i)->nodeType() == DOM::Node::TEXT_NODE) { static_cast(nl->item(i))->setData(str, exception); return; } } // No child text node found, creating one DOM::TextImpl* t = option.getDocument()->createTextNode(str.implementation()); int dummyexception; option.appendChild(t, dummyexception); // #### exec->setException ? return; } // read-only: index case OptionSelected: { option.setSelected(value->toBoolean(exec)); return; } case OptionValue: { option.setValue(str.implementation()); return; } } } break; case ID_INPUT: { DOM::HTMLInputElementImpl& input = static_cast(element); switch (token) { case InputChecked: { input.setChecked(value->toBoolean(exec)); return; } case InputIndeterminate: { input.setIndeterminate(value->toBoolean(exec)); return; } case InputName: { input.setName(str); return; } case InputType: { input.setType(str); return; } case InputValue: { input.setValue(str); return; } case InputSelectionStart: { input.setSelectionStart(value->toInteger(exec)); return; } case InputSelectionEnd: { input.setSelectionEnd (value->toInteger(exec)); return; } } } break; case ID_TEXTAREA: { DOM::HTMLTextAreaElementImpl& textarea = static_cast(element); switch (token) { case TextAreaDefaultValue: { textarea.setDefaultValue(str); return; } case TextAreaName: { textarea.setName(str); return; } case TextAreaValue: { textarea.setValue(str); return; } case TextAreaSelectionStart: { textarea.setSelectionStart(value->toInteger(exec)); return; } case TextAreaSelectionEnd: { textarea.setSelectionEnd (value->toInteger(exec)); return; } } } break; case ID_A: { DOM::HTMLAnchorElementImpl& anchor = static_cast(element); switch (token) { case AnchorSearch: { QString href = getURLArg(ATTR_HREF); KUrl u(href); QString q = str.isEmpty() ? QString() : str.string(); u.setQuery(q); anchor.setAttribute(ATTR_HREF, u.url()); return; } } } break; case ID_IMG: { DOM::HTMLImageElementImpl& image = static_cast(element); switch (token) { case ImageHeight: { image.setHeight(value->toInteger(exec)); return; } case ImageWidth: { image.setWidth (value->toInteger(exec)); return; } } } break; case ID_CANVAS: { DOM::HTMLCanvasElementImpl& canvas = static_cast(element); switch (token) { // ### it may make sense to do something different here, to at least // emulate reflecting properties somewhat. case CanvasWidth: canvas.setAttribute(ATTR_WIDTH, value->toString(exec).domString()); return; case CanvasHeight: canvas.setAttribute(ATTR_HEIGHT, value->toString(exec).domString()); return; } } break; // case ID_FIELDSET: { // DOM::HTMLFieldSetElementImpl& fieldSet = static_cast(element); // // read-only: form // } // break; case ID_SCRIPT: { DOM::HTMLScriptElementImpl& script = static_cast(element); switch (token) { case ScriptText: { script.setText(str); return; } } } break; case ID_TABLE: { DOM::HTMLTableElementImpl& table = static_cast(element); switch (token) { case TableCaption: { table.setCaption(toHTMLTableCaptionElement(value)); return; } // type HTMLTableCaptionElement case TableTHead: { table.setTHead(toHTMLTableSectionElement(value)); return; } // type HTMLTableSectionElement case TableTFoot: { table.setTFoot(toHTMLTableSectionElement(value)); return; } // type HTMLTableSectionElement } } break; case ID_FRAME: { DOM::HTMLFrameElementImpl& frameElement = static_cast(element); switch (token) { // read-only: FrameContentDocument: case FrameLocation: { frameElement.setLocation(str); return; } } } break; } // generic properties switch (token) { case ElementInnerHTML: element.setInnerHTML(str, exception); return; case ElementInnerText: element.setInnerText(str, exception); return; default: kDebug(6070) << "WARNING: KJS::HTMLElement::putValueProperty unhandled token " << token << " thisTag=" << element.tagName().string() << " str=" << str.string(); } } //Prototype mess for this... KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLElementProto, DOMElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLElement", HTMLElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLElementPseudoCtor, "HTMLElement", HTMLElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLHtmlElement", HTMLHtmlElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLHtmlElementPseudoCtor, "HTMLHtmlElement", HTMLHtmlElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLHeadElement", HTMLHeadElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLHeadElementPseudoCtor, "HTMLHeadElement", HTMLHeadElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLinkElement", HTMLLinkElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLinkElementPseudoCtor, "HTMLLinkElement", HTMLLinkElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLTitleElement", HTMLTitleElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTitleElementPseudoCtor, "HTMLTitleElement", HTMLTitleElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLMetaElement", HTMLMetaElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLMetaElementPseudoCtor, "HTMLMetaElement", HTMLMetaElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBaseElement", HTMLBaseElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBaseElementPseudoCtor, "HTMLBaseElement", HTMLBaseElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLIsIndexElement", HTMLIsIndexElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLIsIndexElementPseudoCtor, "HTMLIsIndexElement", HTMLIsIndexElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLStyleElement", HTMLStyleElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLStyleElementPseudoCtor, "HTMLStyleElement", HTMLStyleElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBodyElement", HTMLBodyElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBodyElementPseudoCtor, "HTMLBodyElement", HTMLBodyElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLFormElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLFormElement", HTMLFormElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFormElementPseudoCtor, "HTMLFormElement", HTMLFormElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLSelectElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLSelectElement", HTMLSelectElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLSelectElementPseudoCtor, "HTMLSelectElement", HTMLSelectElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLOptGroupElement", HTMLOptGroupElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLOptGroupElementPseudoCtor, "HTMLOptGroupElement", HTMLOptGroupElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLOptionElement", HTMLOptionElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLOptionElementPseudoCtor, "HTMLOptionElement", HTMLOptionElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLInputElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLInputElement", HTMLInputElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLInputElementPseudoCtor, "HTMLInputElement", HTMLInputElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLTextAreaElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLTextAreaElement", HTMLTextAreaElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTextAreaElementPseudoCtor, "HTMLTextAreaElement", HTMLTextAreaElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLButtonElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLButtonElement", HTMLButtonElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLButtonElementPseudoCtor, "HTMLButtonElement", HTMLButtonElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLabelElement", HTMLLabelElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLabelElementPseudoCtor, "HTMLLabelElement", HTMLLabelElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLFieldSetElement", HTMLFieldSetElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFieldSetElementPseudoCtor, "HTMLFieldSetElement", HTMLFieldSetElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLegendElement", HTMLLegendElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLegendElementPseudoCtor, "HTMLLegendElement", HTMLLegendElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLUListElement", HTMLUListElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLUListElementPseudoCtor, "HTMLUListElement", HTMLUListElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLOListElement", HTMLOListElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLOListElementPseudoCtor, "HTMLOListElement", HTMLOListElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLDListElement", HTMLDListElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLDListElementPseudoCtor, "HTMLDListElement", HTMLDListElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLDirectoryElement", HTMLDirectoryElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLDirectoryElementPseudoCtor, "HTMLDirectoryElement", HTMLDirectoryElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLMenuElement", HTMLMenuElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLMenuElementPseudoCtor, "HTMLMenuElement", HTMLMenuElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLIElement", HTMLLIElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLIElementPseudoCtor, "HTMLLIElement", HTMLLIElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLDivElement", HTMLDivElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLDivElementPseudoCtor, "HTMLDivElement", HTMLDivElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLParagraphElement", HTMLParagraphElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLParagraphElementPseudoCtor, "HTMLParagraphElement", HTMLParagraphElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLHeadingElement", HTMLHeadingElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLHeadingElementPseudoCtor, "HTMLHeadingElement", HTMLHeadingElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBlockQuoteElement", HTMLBlockQuoteElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBlockQuoteElementPseudoCtor, "HTMLBlockQuoteElement", HTMLBlockQuoteElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLQuoteElement", HTMLQuoteElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLQuoteElementPseudoCtor, "HTMLQuoteElement", HTMLQuoteElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLPreElement", HTMLPreElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLPreElementPseudoCtor, "HTMLPreElement", HTMLPreElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBRElement", HTMLBRElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBRElementPseudoCtor, "HTMLBRElement", HTMLBRElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBaseFontElement", HTMLBaseFontElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBaseFontElementPseudoCtor, "HTMLBaseFontElement", HTMLBaseFontElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLFontElement", HTMLFontElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFontElementPseudoCtor, "HTMLFontElement", HTMLFontElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLHRElement", HTMLHRElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLHRElementPseudoCtor, "HTMLHRElement", HTMLHRElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLModElement", HTMLModElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLModElementPseudoCtor, "HTMLModElement", HTMLModElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLAnchorElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLAnchorElement", HTMLAnchorElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLAnchorElementPseudoCtor, "HTMLAnchorElement", HTMLAnchorElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLImageElement", HTMLImageElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLImageElementPseudoCtor, "HTMLImageElement", HTMLImageElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLObjectElement", HTMLObjectElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLObjectElementPseudoCtor, "HTMLObjectElement", HTMLObjectElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLParamElement", HTMLParamElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLParamElementPseudoCtor, "HTMLParamElement", HTMLParamElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLAppletElement", HTMLAppletElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLAppletElementPseudoCtor, "HTMLAppletElement", HTMLAppletElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLMapElement", HTMLMapElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLMapElementPseudoCtor, "HTMLMapElement", HTMLMapElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLAreaElement", HTMLAreaElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLAreaElementPseudoCtor, "HTMLAreaElement", HTMLAreaElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLScriptElement", HTMLScriptElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLScriptElementPseudoCtor, "HTMLScriptElement", HTMLScriptElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLTableElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLTableElement", HTMLTableElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableElementPseudoCtor, "HTMLTableElement", HTMLTableElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLTableCaptionElement", HTMLTableCaptionElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableCaptionElementPseudoCtor, "HTMLTableCaptionElement", HTMLTableCaptionElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLTableColElement", HTMLTableColElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableColElementPseudoCtor, "HTMLTableColElement", HTMLTableColElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLTableSectionElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLTableSectionElement", HTMLTableSectionElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableSectionElementPseudoCtor, "HTMLTableSectionElement", HTMLTableSectionElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLTableRowElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLTableRowElement", HTMLTableRowElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableRowElementPseudoCtor, "HTMLTableRowElement", HTMLTableRowElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLTableCellElement", HTMLTableCellElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableCellElementPseudoCtor, "HTMLTableCellElement", HTMLTableCellElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLFrameSetElement", HTMLFrameSetElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFrameSetElementPseudoCtor, "HTMLFrameSetElement", HTMLFrameSetElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLayerElement", HTMLLayerElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLayerElementPseudoCtor, "HTMLLayerElement", HTMLLayerElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLFrameElement", HTMLFrameElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFrameElementPseudoCtor, "HTMLFrameElement", HTMLFrameElementProto) KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLIFrameElement", HTMLIFrameElementProto, HTMLElementProto) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLIFrameElementPseudoCtor, "HTMLIFrameElement", HTMLIFrameElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLMarqueeElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLMarqueeElement", HTMLMarqueeElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLMarqueeElementPseudoCtor, "HTMLMarqueeElement", HTMLMarqueeElementProto) KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLCanvasElementProto, HTMLElementProto) KJS_IMPLEMENT_PROTOTYPE("HTMLCanvasElement", HTMLCanvasElementProto, HTMLElementFunction) IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLCanvasElementPseudoCtor, "HTMLCanvasElement", HTMLCanvasElementProto) static JSObject* prototypeForID(ExecState* exec, DOM::NodeImpl::Id id) { switch (id) { case ID_HTML: return HTMLHtmlElementProto::self(exec); case ID_HEAD: return HTMLHeadElementProto::self(exec); case ID_LINK: return HTMLLinkElementProto::self(exec); case ID_TITLE: return HTMLTitleElementProto::self(exec); case ID_META: return HTMLMetaElementProto::self(exec); case ID_BASE: return HTMLBaseElementProto::self(exec); case ID_ISINDEX: return HTMLIsIndexElementProto::self(exec); case ID_STYLE: return HTMLStyleElementProto::self(exec); case ID_BODY: return HTMLBodyElementProto::self(exec); case ID_FORM: return HTMLFormElementProto::self(exec); case ID_SELECT: return HTMLSelectElementProto::self(exec); case ID_OPTGROUP: return HTMLOptGroupElementProto::self(exec); case ID_OPTION: return HTMLOptionElementProto::self(exec); case ID_INPUT: return HTMLInputElementProto::self(exec); case ID_TEXTAREA: return HTMLTextAreaElementProto::self(exec); case ID_BUTTON: return HTMLButtonElementProto::self(exec); case ID_LABEL: return HTMLLabelElementProto::self(exec); case ID_FIELDSET: return HTMLFieldSetElementProto::self(exec); case ID_LEGEND: return HTMLLegendElementProto::self(exec); case ID_UL: return HTMLUListElementProto::self(exec); case ID_OL: return HTMLOListElementProto::self(exec); case ID_DL: return HTMLDListElementProto::self(exec); case ID_DIR: return HTMLDirectoryElementProto::self(exec); case ID_MENU: return HTMLMenuElementProto::self(exec); case ID_LI: return HTMLLIElementProto::self(exec); case ID_DIV: return HTMLDivElementProto::self(exec); case ID_P: return HTMLParagraphElementProto::self(exec); case ID_H1: case ID_H2: case ID_H3: case ID_H4: case ID_H5: case ID_H6: return HTMLHeadingElementProto::self(exec); case ID_BLOCKQUOTE: return HTMLBlockQuoteElementProto::self(exec); case ID_Q: return HTMLQuoteElementProto::self(exec); case ID_PRE: return HTMLPreElementProto::self(exec); case ID_BR: return HTMLBRElementProto::self(exec); case ID_BASEFONT: return HTMLBaseFontElementProto::self(exec); case ID_FONT: return HTMLFontElementProto::self(exec); case ID_HR: return HTMLHRElementProto::self(exec); case ID_INS: case ID_DEL: return HTMLModElementProto::self(exec); case ID_A: return HTMLAnchorElementProto::self(exec); case ID_IMG: return HTMLImageElementProto::self(exec); case ID_OBJECT: return HTMLObjectElementProto::self(exec); case ID_PARAM: return HTMLParamElementProto::self(exec); case ID_APPLET: return HTMLAppletElementProto::self(exec); case ID_MAP: return HTMLMapElementProto::self(exec); case ID_AREA: return HTMLAreaElementProto::self(exec); case ID_SCRIPT: return HTMLScriptElementProto::self(exec); case ID_TABLE: return HTMLTableElementProto::self(exec); case ID_CAPTION: return HTMLTableCaptionElementProto::self(exec); case ID_COL: case ID_COLGROUP: return HTMLTableColElementProto::self(exec); case ID_THEAD: case ID_TBODY: case ID_TFOOT: return HTMLTableSectionElementProto::self(exec); case ID_TR: return HTMLTableRowElementProto::self(exec); case ID_TD: case ID_TH: return HTMLTableCellElementProto::self(exec); case ID_FRAMESET: return HTMLFrameSetElementProto::self(exec); case ID_LAYER: return HTMLLayerElementProto::self(exec); case ID_FRAME: return HTMLFrameElementProto::self(exec); case ID_IFRAME: return HTMLIFrameElementProto::self(exec); case ID_MARQUEE: return HTMLMarqueeElementProto::self(exec); case ID_CANVAS: return HTMLCanvasElementProto::self(exec); default: return HTMLElementProto::self(exec); } } // ------------------------------------------------------------------------- /* Source for HTMLCollectionProtoTable. @begin HTMLCollectionProtoTable 3 item HTMLCollection::Item DontDelete|Function 1 namedItem HTMLCollection::NamedItem DontDelete|Function 1 tags HTMLCollection::Tags DontDelete|Function 1 @end */ KJS_DEFINE_PROTOTYPE(HTMLCollectionProto) KJS_IMPLEMENT_PROTOFUNC(HTMLCollectionProtoFunc) KJS_IMPLEMENT_PROTOTYPE("HTMLCollection", HTMLCollectionProto,HTMLCollectionProtoFunc) const ClassInfo KJS::HTMLCollection::info = { "HTMLCollection", 0, 0, 0 }; KJS::HTMLCollection::HTMLCollection(ExecState *exec, DOM::HTMLCollectionImpl* c) : DOMObject(HTMLCollectionProto::self(exec)), m_impl(c), hidden(false) {} KJS::HTMLCollection::HTMLCollection(JSObject* proto, DOM::HTMLCollectionImpl* c) : DOMObject(proto), m_impl(c), hidden(false) {} KJS::HTMLCollection::~HTMLCollection() { ScriptInterpreter::forgetDOMObject(m_impl.get()); } bool KJS::HTMLCollection::toBoolean(ExecState *) const { return !hidden; } JSValue* HTMLCollection::indexGetter(ExecState *exec, unsigned index) { return getDOMNode(exec, m_impl->item(index)); } void KJS::HTMLCollection::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) { for (unsigned i = 0; i < m_impl->length(); ++i) propertyNames.add(Identifier::from(i)); propertyNames.add(exec->propertyNames().length); JSObject::getPropertyNames(exec, propertyNames); } JSValue *HTMLCollection::lengthGetter(ExecState *, JSObject*, const Identifier&, const PropertySlot& slot) { HTMLCollection *thisObj = static_cast(slot.slotBase()); return jsNumber(thisObj->m_impl->length()); } JSValue *HTMLCollection::nameGetter(ExecState *exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot) { HTMLCollection *thisObj = static_cast(slot.slotBase()); return thisObj->getNamedItems(exec, propertyName); } bool KJS::HTMLCollection::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot& slot) { #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLCollection::getOwnPropertySlot " << propertyName.ascii(); #endif if (propertyName.isEmpty()) return false; if (propertyName == exec->propertyNames().length) { #ifdef KJS_VERBOSE kDebug(6070) << " collection length is " << m_impl->length(); #endif slot.setCustom(this, lengthGetter); return true; } // Look in the prototype (for functions) before assuming it's an item's name JSValue *proto = prototype(); if (proto->isObject() && static_cast(proto)->hasProperty(exec, propertyName)) return false; // name or index ? if (getIndexSlot(this, *m_impl, propertyName, slot)) return true; if (!getNamedItems(exec, propertyName)->isUndefined()) { slot.setCustom(this, nameGetter); return true; } return DOMObject::getOwnPropertySlot(exec, propertyName, slot); } // HTMLCollections are strange objects, they support both get and call, // so that document.forms.item(0) and document.forms(0) both work. JSValue* KJS::HTMLCollection::callAsFunction(ExecState *exec, JSObject *, const List &args) { // Do not use thisObj here. It can be the HTMLDocument, in the document.forms(i) case. /*if( thisObj.imp() != this ) { kDebug(6070) << "WARNING: thisObj.imp() != this in HTMLCollection::tryCall"; KJS::printInfo(exec,"KJS::HTMLCollection::tryCall thisObj",thisObj,-1); KJS::printInfo(exec,"KJS::HTMLCollection::tryCall this",Value(this),-1); }*/ // Also, do we need the TypeError test here ? HTMLCollectionImpl &collection = *m_impl; // Also, do we need the TypeError test here ? if (args.size() == 1) { // support for document.all() etc. bool ok; UString s = args[0]->toString(exec); unsigned int u = s.toUInt32(&ok, false); if (ok) return getDOMNode(exec, collection.item(u)); // support for document.images('') etc. return getNamedItems(exec, Identifier(s)); } else if (args.size() >= 1) // the second arg, if set, is the index of the item we want { bool ok; UString s = args[0]->toString(exec); unsigned int u = args[1]->toString(exec).toUInt32(&ok, false); if (ok) { DOM::DOMString pstr = s.domString(); DOM::NodeImpl* node = collection.namedItem(pstr); while (node) { if (!u) return getDOMNode(exec,node); node = collection.nextNamedItem(pstr); --u; } } } return jsUndefined(); } JSValue* KJS::HTMLCollection::getNamedItems(ExecState *exec, const Identifier &propertyName) const { #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLCollection::getNamedItems " << propertyName.ascii(); #endif DOM::DOMString pstr = propertyName.domString(); QList matches = m_impl->namedItems(pstr); if (!matches.isEmpty()) { if (matches.size() == 1) { #ifdef KJS_VERBOSE kDebug(6070) << "returning single node"; #endif return getDOMNode(exec,matches[0]); } else { // multiple items, return a collection QList > nodes; foreach (DOM::NodeImpl* node, matches) nodes.append(node); #ifdef KJS_VERBOSE kDebug(6070) << "returning list of " << matches.count() << " nodes"; #endif return new DOMNamedNodesCollection(exec, nodes); } } #ifdef KJS_VERBOSE kDebug(6070) << "not found"; #endif return jsUndefined(); } JSValue* KJS::HTMLCollectionProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { KJS_CHECK_THIS( KJS::HTMLCollection, thisObj ); HTMLCollectionImpl &coll = *static_cast(thisObj)->impl(); switch (id) { case KJS::HTMLCollection::Item: { // support for item() (DOM) UString s = args[0]->toString(exec); bool ok; unsigned int u = s.toUInt32(&ok, false); if (ok) { return getDOMNode(exec,coll.item(u)); } // support for item('') (IE only) kWarning() << "non-standard HTMLCollection.item('" << s.ascii() << "') called, use namedItem instead"; return static_cast(thisObj)->getNamedItems(exec, Identifier(s)); } case KJS::HTMLCollection::Tags: { DOM::DOMString tagName = args[0]->toString(exec).domString(); DOM::NodeListImpl* list; // getElementsByTagName exists in Document and in Element, pick up the right one if ( coll.base()->nodeType() == DOM::Node::DOCUMENT_NODE ) { DOM::DocumentImpl* doc = static_cast(coll.base()); list = doc->getElementsByTagName(tagName); #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLCollectionProtoFunc::callAsFunction document.tags(" << tagName.string() << ") -> " << list->length() << " items in node list"; #endif } else { DOM::ElementImpl* e = static_cast(coll.base()); list = e->getElementsByTagName(tagName); #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLCollectionProtoFunc::tryCall element.tags(" << tagName.string() << ") -> " << list->length() << " items in node list"; #endif } return getDOMNodeList(exec, list); } case KJS::HTMLCollection::NamedItem: { JSValue *val = static_cast(thisObj)->getNamedItems(exec, Identifier(args[0]->toString(exec))); // Must return null when asking for a named item that isn't in the collection // (DOM2 testsuite, HTMLCollection12 test) if ( val->type() == KJS::UndefinedType ) return jsNull(); else return val; } default: return jsUndefined(); } } // ------------------------------------------------------------------------- /* Source for HTMLSelectCollectionProtoTable. @begin HTMLSelectCollectionProtoTable 1 add HTMLSelectCollection::Add DontDelete|Function 2 @end */ KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLSelectCollectionProto, HTMLCollectionProto) KJS_IMPLEMENT_PROTOFUNC(HTMLSelectCollectionProtoFunc) KJS_IMPLEMENT_PROTOTYPE("HTMLOptionsCollection", HTMLSelectCollectionProto, HTMLSelectCollectionProtoFunc) const ClassInfo KJS::HTMLSelectCollection::info = { "HTMLOptionsCollection", &HTMLCollection::info, 0, 0 }; KJS::HTMLSelectCollection::HTMLSelectCollection(ExecState *exec, DOM::HTMLCollectionImpl* c, DOM::HTMLSelectElementImpl* e) : HTMLCollection(HTMLSelectCollectionProto::self(exec), c), element(e) { } JSValue *HTMLSelectCollection::selectedIndexGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot) { HTMLSelectCollection *thisObj = static_cast(slot.slotBase()); return jsNumber(thisObj->element->selectedIndex()); } JSValue *HTMLSelectCollection::selectedValueGetter(ExecState*, JSObject*, const Identifier& propertyName, const PropertySlot& slot) { HTMLSelectCollection *thisObj = static_cast(slot.slotBase()); return jsString(thisObj->element->value()); } bool KJS::HTMLSelectCollection::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot& slot) { if (p == "selectedIndex") { slot.setCustom(this, selectedIndexGetter); return true; } else if (p == "value") { slot.setCustom(this, selectedValueGetter); return true; } return HTMLCollection::getOwnPropertySlot(exec, p, slot); } void KJS::HTMLSelectCollection::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int) { DOMExceptionTranslator exception(exec); #ifdef KJS_VERBOSE kDebug(6070) << "KJS::HTMLSelectCollection::put " << propertyName.qstring(); #endif if ( propertyName == "selectedIndex" ) { element->setSelectedIndex( value->toInteger( exec ) ); return; } // resize ? else if (propertyName == exec->propertyNames().length) { uint32_t newLen; bool converted = value->getUInt32(newLen); if (!converted) { return; } long diff = element->length() - newLen; if (diff < 0) { // add dummy elements do { ElementImpl *option = element->getDocument()->createElement("option", exception); if (exception.triggered()) return; element->add(static_cast(option), 0, exception); if (exception.triggered()) return; } while (++diff); } else // remove elements while (diff-- > 0) element->remove(newLen + diff); return; } // an index ? bool ok; unsigned int u = propertyName.qstring().toULong(&ok); if (!ok) return; if (value->type() == NullType || value->type() == UndefinedType) { // null and undefined delete. others, too ? element->remove(u); return; } // is v an option element ? DOM::NodeImpl* node = KJS::toNode(value); if (!node || node->id() != ID_OPTION) return; DOM::HTMLOptionElementImpl* option = static_cast(node); if ( option->getDocument() != element->getDocument() ) option = static_cast(element->ownerDocument()->importNode(option, true, exception)); if (exception.triggered()) return; long diff = long(u) - element->length(); DOM::HTMLElementImpl* before = 0; // out of array bounds ? first insert empty dummies if (diff > 0) { while (diff--) { element->add( static_cast(element->getDocument()->createElement("OPTION")), before, exception); if (exception.triggered()) return; } // replace an existing entry ? } else if (diff < 0) { SharedPtr options = element->options(); before = static_cast(options->item(u+1)); element->remove(u); } // finally add the new element element->add(option, before, exception); } JSValue* KJS::HTMLSelectCollectionProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { KJS_CHECK_THIS( KJS::HTMLSelectCollection, thisObj ); DOM::HTMLSelectElementImpl* element = static_cast(thisObj)->toElement(); switch (id) { case KJS::HTMLSelectCollection::Add: { //Non-standard select.options.add. //The first argument is the item, 2nd is offset. //IE and Mozilla are both quite picky here, too... DOM::NodeImpl* node = KJS::toNode(args[0]); if (!node || node->id() != ID_OPTION) return throwError(exec, GeneralError, "Invalid argument to HTMLOptionsCollection::add"); DOM::HTMLOptionElementImpl* option = static_cast(node); int pos = 0; //By default append, if not specified or null.. if (args[1]->isUndefined()) pos = element->length(); else pos = (int)args[1]->toNumber(exec); if (pos < 0) return throwError(exec, GeneralError, "Invalid index argument to HTMLOptionsCollection::add"); DOMExceptionTranslator exception(exec); if (pos >= element->length()) { //Append element->add(option, 0, exception); } else { //Find what to prepend before.. QVector items = element->listItems(); int dummy; element->insertBefore(option, items.at(pos), dummy); } return jsUndefined(); break; } default: break; } return jsUndefined(); } ////////////////////// Option Object //////////////////////// OptionConstructorImp::OptionConstructorImp(ExecState *exec, DOM::DocumentImpl* d) : JSObject(), doc(d) { // ## isn't there some redundancy between JSObject::_proto and the "prototype" property ? //put(exec,"prototype", ...,DontEnum|DontDelete|ReadOnly); // no. of arguments for constructor // ## is 4 correct ? 0 to 4, it seems to be put(exec, exec->propertyNames().length, jsNumber(4), ReadOnly|DontDelete|DontEnum); } bool OptionConstructorImp::implementsConstruct() const { return true; } JSObject *OptionConstructorImp::construct(ExecState *exec, const List &args) { DOMExceptionTranslator exception(exec); DOM::ElementImpl* el = doc->createElement("OPTION"); DOM::HTMLOptionElementImpl* opt = static_cast(el); int sz = args.size(); SharedPtr t = doc->createTextNode(""); int dummyexception = 0;// #### exec->setException ? opt->appendChild(t.get(), dummyexception); if (sz > 0) t->setData(args[0]->toString(exec).domString(), exception); // set the text if (sz > 1) opt->setValue(args[1]->toString(exec).domString().implementation()); if (sz > 2) opt->setDefaultSelected(args[2]->toBoolean(exec)); if (sz > 3) opt->setSelected(args[3]->toBoolean(exec)); return getDOMNode(exec,opt)->getObject(); } ////////////////////// Image Object //////////////////////// //Like in other browsers, we merely make a new HTMLImageElement //not in tree for this. ImageConstructorImp::ImageConstructorImp(ExecState *, DOM::DocumentImpl* d) : JSObject(), doc(d) { } bool ImageConstructorImp::implementsConstruct() const { return true; } JSObject *ImageConstructorImp::construct(ExecState *exec, const List &list) { bool widthSet = false, heightSet = false; int width = 0, height = 0; if (list.size() > 0) { widthSet = true; JSValue *w = list.at(0); width = w->toInt32(exec); } if (list.size() > 1) { heightSet = true; JSValue *h = list.at(1); height = h->toInt32(exec); } HTMLImageElementImpl* image = static_cast(doc->createElement("image")); if (widthSet) image->setAttribute(ATTR_WIDTH, QString::number(width)); if (heightSet) image->setAttribute(ATTR_HEIGHT, QString::number(height)); return getDOMNode(exec,image)->getObject(); } JSValue* getHTMLCollection(ExecState *exec, DOM::HTMLCollectionImpl* c, bool hide) { assert(!c || c->getType() != HTMLCollectionImpl::SELECT_OPTIONS); JSValue *coll = cacheDOMObject(exec, c); if (hide) { KJS::HTMLCollection *impl = static_cast(coll); impl->hide(); } return coll; } JSValue* getSelectHTMLCollection(ExecState *exec, DOM::HTMLCollectionImpl* c, DOM::HTMLSelectElementImpl* e) { assert(!c || c->getType() == HTMLCollectionImpl::SELECT_OPTIONS); DOMObject *ret; if (!c) return jsNull(); ScriptInterpreter* interp = static_cast(exec->dynamicInterpreter()); if ((ret = interp->getDOMObject(c))) return ret; else { ret = new HTMLSelectCollection(exec, c, e); interp->putDOMObject(c,ret); return ret; } } } //namespace KJS diff --git a/khtml/ecma/kjs_window.cpp b/khtml/ecma/kjs_window.cpp index 32bbec2acd..d45b3b9c3a 100644 --- a/khtml/ecma/kjs_window.cpp +++ b/khtml/ecma/kjs_window.cpp @@ -1,3001 +1,3001 @@ // -*- c-basic-offset: 2 -*- /* * This file is part of the KDE libraries * Copyright (C) 2000-2003 Harri Porten (porten@kde.org) * Copyright (C) 2001-2003 David Faure (faure@kde.org) * Copyright (C) 2003 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "kjs_window.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef KONQ_EMBEDDED #include #include #endif #include #include #include #include #include #include #include "kjs_proxy.h" #include "kjs_navigator.h" #include "kjs_mozilla.h" #include "kjs_html.h" #include "kjs_range.h" #include "kjs_traversal.h" #include "kjs_css.h" #include "kjs_events.h" #include "kjs_views.h" #include "kjs_audio.h" #include "kjs_context2d.h" #include "xmlhttprequest.h" #include "xmlserializer.h" #include "domparser.h" #include using namespace KJS; namespace KJS { class History : public JSObject { friend class HistoryFunc; public: History(ExecState *exec, KHTMLPart *p) : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { } virtual bool getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot); JSValue *getValueProperty(ExecState *exec, int token) const; virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; enum { Back, Forward, Go, Length }; private: QPointer part; }; class External : public JSObject { friend class ExternalFunc; public: External(ExecState *exec, KHTMLPart *p) : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { } virtual bool getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; enum { AddFavorite }; private: QPointer part; }; class FrameArray : public JSObject { public: FrameArray(ExecState *exec, KHTMLPart *p) : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { } virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&); JSValue *getValueProperty(ExecState *exec, int token); virtual UString toString(ExecState *exec) const; enum { Length, Location }; JSValue *indexGetter(ExecState *, unsigned index); virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args); virtual bool implementsCall() const { return true; } private: static JSValue *nameGetter(ExecState *, JSObject*, const Identifier&, const PropertySlot&); static JSValue *nameFallBackGetter(ExecState *, JSObject*, const Identifier&, const PropertySlot&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; QPointer part; }; } //namespace KJS #include "kjs_window.lut.h" namespace KJS { ////////////////////// Screen Object //////////////////////// // table for screen object /* @begin ScreenTable 7 height Screen::Height DontEnum|ReadOnly width Screen::Width DontEnum|ReadOnly colorDepth Screen::ColorDepth DontEnum|ReadOnly pixelDepth Screen::PixelDepth DontEnum|ReadOnly availLeft Screen::AvailLeft DontEnum|ReadOnly availTop Screen::AvailTop DontEnum|ReadOnly availHeight Screen::AvailHeight DontEnum|ReadOnly availWidth Screen::AvailWidth DontEnum|ReadOnly @end */ const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 }; // We set the object prototype so that toString is implemented Screen::Screen(ExecState *exec) : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()) {} bool Screen::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { #ifdef KJS_VERBOSE kDebug(6070) << "Screen::getPropertyName " << propertyName.qstring(); #endif return getStaticValueSlot(exec, &ScreenTable, this, propertyName, slot); } JSValue *Screen::getValueProperty(ExecState *exec, int token) const { QWidget *thisWidget = Window::retrieveActive(exec)->part()->widget(); QRect sg = KGlobalSettings::desktopGeometry(thisWidget); switch( token ) { case Height: return jsNumber(sg.height()); case Width: return jsNumber(sg.width()); case ColorDepth: case PixelDepth: return jsNumber(thisWidget->depth()); case AvailLeft: { #if defined Q_WS_X11 && ! defined K_WS_QTONLY QRect clipped = KWindowSystem::workArea().intersect(sg); return jsNumber(clipped.x()-sg.x()); #else return jsNumber(10); #endif } case AvailTop: { #if defined Q_WS_X11 && ! defined K_WS_QTONLY QRect clipped = KWindowSystem::workArea().intersect(sg); return jsNumber(clipped.y()-sg.y()); #else return jsNumber(10); #endif } case AvailHeight: { #if defined Q_WS_X11 && ! defined K_WS_QTONLY QRect clipped = KWindowSystem::workArea().intersect(sg); return jsNumber(clipped.height()); #else return jsNumber(100); #endif } case AvailWidth: { #if defined Q_WS_X11 && ! defined K_WS_QTONLY QRect clipped = KWindowSystem::workArea().intersect(sg); return jsNumber(clipped.width()); #else return jsNumber(100); #endif } default: kDebug(6070) << "WARNING: Screen::getValueProperty unhandled token " << token; return jsUndefined(); } } ////////////////////// Window Object //////////////////////// const ClassInfo Window::info = { "Window", &DOMAbstractView::info, &WindowTable, 0 }; /* @begin WindowTable 233 atob Window::AToB DontDelete|Function 1 btoa Window::BToA DontDelete|Function 1 closed Window::Closed DontDelete|ReadOnly crypto Window::Crypto DontDelete|ReadOnly defaultStatus Window::DefaultStatus DontDelete defaultstatus Window::DefaultStatus DontDelete status Window::Status DontDelete document Window::Document DontDelete|ReadOnly frameElement Window::FrameElement DontDelete|ReadOnly frames Window::Frames DontDelete|ReadOnly history Window::_History DontDelete|ReadOnly external Window::_External DontDelete|ReadOnly event Window::Event DontDelete|ReadOnly innerHeight Window::InnerHeight DontDelete|ReadOnly innerWidth Window::InnerWidth DontDelete|ReadOnly length Window::Length DontDelete|ReadOnly location Window::_Location DontDelete name Window::Name DontDelete navigator Window::_Navigator DontDelete|ReadOnly clientInformation Window::ClientInformation DontDelete|ReadOnly konqueror Window::_Konqueror DontDelete|ReadOnly offscreenBuffering Window::OffscreenBuffering DontDelete|ReadOnly opener Window::Opener DontDelete|ReadOnly outerHeight Window::OuterHeight DontDelete|ReadOnly outerWidth Window::OuterWidth DontDelete|ReadOnly pageXOffset Window::PageXOffset DontDelete|ReadOnly pageYOffset Window::PageYOffset DontDelete|ReadOnly parent Window::Parent DontDelete|ReadOnly personalbar Window::Personalbar DontDelete|ReadOnly screenX Window::ScreenX DontDelete|ReadOnly screenY Window::ScreenY DontDelete|ReadOnly scrollbars Window::Scrollbars DontDelete|ReadOnly scroll Window::Scroll DontDelete|Function 2 scrollBy Window::ScrollBy DontDelete|Function 2 scrollTo Window::ScrollTo DontDelete|Function 2 scrollX Window::ScrollX DontDelete|ReadOnly scrollY Window::ScrollY DontDelete|ReadOnly moveBy Window::MoveBy DontDelete|Function 2 moveTo Window::MoveTo DontDelete|Function 2 resizeBy Window::ResizeBy DontDelete|Function 2 resizeTo Window::ResizeTo DontDelete|Function 2 self Window::Self DontDelete|ReadOnly window Window::_Window DontDelete|ReadOnly top Window::Top DontDelete|ReadOnly screen Window::_Screen DontDelete|ReadOnly alert Window::Alert DontDelete|Function 1 confirm Window::Confirm DontDelete|Function 1 prompt Window::Prompt DontDelete|Function 2 open Window::Open DontDelete|Function 3 setTimeout Window::SetTimeout DontDelete|Function 2 clearTimeout Window::ClearTimeout DontDelete|Function 1 focus Window::Focus DontDelete|Function 0 blur Window::Blur DontDelete|Function 0 close Window::Close DontDelete|Function 0 setInterval Window::SetInterval DontDelete|Function 2 clearInterval Window::ClearInterval DontDelete|Function 1 captureEvents Window::CaptureEvents DontDelete|Function 0 releaseEvents Window::ReleaseEvents DontDelete|Function 0 print Window::Print DontDelete|Function 0 addEventListener Window::AddEventListener DontDelete|Function 3 removeEventListener Window::RemoveEventListener DontDelete|Function 3 # Normally found in prototype. Add to window object itself to make them # accessible in closed and cross-site windows valueOf Window::ValueOf DontDelete|Function 0 toString Window::ToString DontDelete|Function 0 # IE extension navigate Window::Navigate DontDelete|Function 1 # Mozilla extension sidebar Window::SideBar DontDelete|ReadOnly getComputedStyle Window::GetComputedStyle DontDelete|Function 2 # Warning, when adding a function to this object you need to add a case in Window::get # Event handlers # IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect, # ondeactivate, onhelp, onmovestart/end, onresizestart/end, onscroll. # It doesn't have onabort, onchange, ondragdrop (but NS has that last one). onabort Window::Onabort DontDelete onblur Window::Onblur DontDelete onchange Window::Onchange DontDelete onclick Window::Onclick DontDelete ondblclick Window::Ondblclick DontDelete ondragdrop Window::Ondragdrop DontDelete onerror Window::Onerror DontDelete onfocus Window::Onfocus DontDelete onkeydown Window::Onkeydown DontDelete onkeypress Window::Onkeypress DontDelete onkeyup Window::Onkeyup DontDelete onload Window::Onload DontDelete onmousedown Window::Onmousedown DontDelete onmousemove Window::Onmousemove DontDelete onmouseout Window::Onmouseout DontDelete onmouseover Window::Onmouseover DontDelete onmouseup Window::Onmouseup DontDelete onmove Window::Onmove DontDelete onreset Window::Onreset DontDelete onresize Window::Onresize DontDelete onselect Window::Onselect DontDelete onsubmit Window::Onsubmit DontDelete onunload Window::Onunload DontDelete # Constructors/constant tables Node Window::Node DontDelete Event Window::EventCtor DontDelete Range Window::Range DontDelete NodeFilter Window::NodeFilter DontDelete DOMException Window::DOMException DontDelete RangeException Window::RangeException DontDelete CSSRule Window::CSSRule DontDelete MutationEvent Window::MutationEventCtor DontDelete KeyboardEvent Window::KeyboardEventCtor DontDelete EventException Window::EventExceptionCtor DontDelete Audio Window::Audio DontDelete|ReadOnly Image Window::Image DontDelete|ReadOnly Option Window::Option DontDelete|ReadOnly XMLHttpRequest Window::XMLHttpRequest DontDelete|ReadOnly XMLSerializer Window::XMLSerializer DontDelete|ReadOnly DOMParser Window::DOMParser DontDelete|ReadOnly # Mozilla dom emulation ones. Element Window::ElementCtor DontDelete Document Window::DocumentCtor DontDelete #this one is an alias since we don't have a separate XMLDocument XMLDocument Window::DocumentCtor DontDelete HTMLElement Window::HTMLElementCtor DontDelete HTMLDocument Window::HTMLDocumentCtor DontDelete HTMLHtmlElement Window::HTMLHtmlElementCtor DontDelete HTMLHeadElement Window::HTMLHeadElementCtor DontDelete HTMLLinkElement Window::HTMLLinkElementCtor DontDelete HTMLTitleElement Window::HTMLTitleElementCtor DontDelete HTMLMetaElement Window::HTMLMetaElementCtor DontDelete HTMLBaseElement Window::HTMLBaseElementCtor DontDelete HTMLIsIndexElement Window::HTMLIsIndexElementCtor DontDelete HTMLStyleElement Window::HTMLStyleElementCtor DontDelete HTMLBodyElement Window::HTMLBodyElementCtor DontDelete HTMLFormElement Window::HTMLFormElementCtor DontDelete HTMLSelectElement Window::HTMLSelectElementCtor DontDelete HTMLOptGroupElement Window::HTMLOptGroupElementCtor DontDelete HTMLOptionElement Window::HTMLOptionElementCtor DontDelete HTMLInputElement Window::HTMLInputElementCtor DontDelete HTMLTextAreaElement Window::HTMLTextAreaElementCtor DontDelete HTMLButtonElement Window::HTMLButtonElementCtor DontDelete HTMLLabelElement Window::HTMLLabelElementCtor DontDelete HTMLFieldSetElement Window::HTMLFieldSetElementCtor DontDelete HTMLLegendElement Window::HTMLLegendElementCtor DontDelete HTMLUListElement Window::HTMLUListElementCtor DontDelete HTMLOListElement Window::HTMLOListElementCtor DontDelete HTMLDListElement Window::HTMLDListElementCtor DontDelete HTMLDirectoryElement Window::HTMLDirectoryElementCtor DontDelete HTMLMenuElement Window::HTMLMenuElementCtor DontDelete HTMLLIElement Window::HTMLLIElementCtor DontDelete HTMLDivElement Window::HTMLDivElementCtor DontDelete HTMLParagraphElement Window::HTMLParagraphElementCtor DontDelete HTMLHeadingElement Window::HTMLHeadingElementCtor DontDelete HTMLBlockQuoteElement Window::HTMLBlockQuoteElementCtor DontDelete HTMLQuoteElement Window::HTMLQuoteElementCtor DontDelete HTMLPreElement Window::HTMLPreElementCtor DontDelete HTMLBRElement Window::HTMLBRElementCtor DontDelete HTMLBaseFontElement Window::HTMLBaseFontElementCtor DontDelete HTMLFontElement Window::HTMLFontElementCtor DontDelete HTMLHRElement Window::HTMLHRElementCtor DontDelete HTMLModElement Window::HTMLModElementCtor DontDelete HTMLAnchorElement Window::HTMLAnchorElementCtor DontDelete HTMLImageElement Window::HTMLImageElementCtor DontDelete HTMLObjectElement Window::HTMLObjectElementCtor DontDelete HTMLParamElement Window::HTMLParamElementCtor DontDelete HTMLAppletElement Window::HTMLAppletElementCtor DontDelete HTMLMapElement Window::HTMLMapElementCtor DontDelete HTMLAreaElement Window::HTMLAreaElementCtor DontDelete HTMLScriptElement Window::HTMLScriptElementCtor DontDelete HTMLTableElement Window::HTMLTableElementCtor DontDelete HTMLTableCaptionElement Window::HTMLTableCaptionElementCtor DontDelete HTMLTableColElement Window::HTMLTableColElementCtor DontDelete HTMLTableSectionElement Window::HTMLTableSectionElementCtor DontDelete HTMLTableRowElement Window::HTMLTableRowElementCtor DontDelete HTMLTableCellElement Window::HTMLTableCellElementCtor DontDelete HTMLFrameSetElement Window::HTMLFrameSetElementCtor DontDelete HTMLLayerElement Window::HTMLLayerElementCtor DontDelete HTMLFrameElement Window::HTMLFrameElementCtor DontDelete HTMLIFrameElement Window::HTMLIFrameElementCtor DontDelete HTMLCanvasElement Window::HTMLCanvasElementCtor DontDelete CSSStyleDeclaration Window::CSSStyleDeclarationCtor DontDelete CanvasRenderingContext2D Window::Context2DCtor DontDelete @end */ KJS_IMPLEMENT_PROTOFUNC(WindowFunc) Window::Window(khtml::ChildFrame *p) : JSObject(/*no proto*/), m_frame(p), screen(0), history(0), external(0), m_frames(0), loc(0), m_evt(0) { winq = new WindowQObject(this); //kDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name(); } Window::~Window() { delete winq; } Window *Window::retrieveWindow(KParts::ReadOnlyPart *p) { JSObject *obj = retrieve( p )->getObject(); #ifndef NDEBUG // obj should never be null, except when javascript has been disabled in that part. KHTMLPart *part = qobject_cast(p); if ( part && part->jScriptEnabled() ) { assert( obj ); #ifndef QWS assert( dynamic_cast(obj) ); // type checking #endif } #endif if ( !obj ) // JS disabled return 0; return static_cast(obj); } Window *Window::retrieveActive(ExecState *exec) { JSValue *imp = exec->dynamicInterpreter()->globalObject(); assert( imp ); #ifndef QWS assert( dynamic_cast(imp) ); #endif return static_cast(imp); } JSValue *Window::retrieve(KParts::ReadOnlyPart *p) { assert(p); KHTMLPart * part = qobject_cast(p); KJSProxy *proxy = 0L; if (!part) { part = qobject_cast(p->parent()); if (part) proxy = part->framejScript(p); } else proxy = part->jScript(); if (proxy) { #ifdef KJS_VERBOSE kDebug(6070) << "Window::retrieve part=" << part << " '" << part->objectName() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject(); #endif return proxy->interpreter()->globalObject(); // the Global object is the "window" } else { #ifdef KJS_VERBOSE kDebug(6070) << "Window::retrieve part=" << p << " '" << p->objectName() << "' no jsproxy."; #endif return jsUndefined(); // This can happen with JS disabled on the domain of that window } } Location *Window::location() const { if (!loc) const_cast(this)->loc = new Location(m_frame); return loc; } JSObject* Window::frames( ExecState* exec ) const { KHTMLPart *part = qobject_cast(m_frame->m_part); if (part) return m_frames ? m_frames : (const_cast(this)->m_frames = new FrameArray(exec, part)); return 0L; } // reference our special objects during garbage collection void Window::mark() { JSObject::mark(); if (screen && !screen->marked()) screen->mark(); if (history && !history->marked()) history->mark(); if (external && !external->marked()) external->mark(); if (m_frames && !m_frames->marked()) m_frames->mark(); //kDebug(6070) << "Window::mark " << this << " marking loc=" << loc; if (loc && !loc->marked()) loc->mark(); if (winq) winq->mark(); } UString Window::toString(ExecState *) const { return "[object Window]"; } bool Window::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { #ifdef KJS_VERBOSE kDebug(6070) << "Window("<m_part.isNull()) { const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName); if (entry) { switch (entry->value) { case Closed: case _Location: case ValueOf: case ToString: getSlotFromEntry(entry, this, slot); return true; default: break; } } slot.setUndefined(this); return true; } // Look for overrides first JSValue **val = getDirectLocation(propertyName); if (val) { if (isSafeScript(exec)) - slot.setValueSlot(this, val); + fillDirectLocationSlot(slot, val); else slot.setUndefined(this); return true; } const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName); KHTMLPart *part = qobject_cast(m_frame->m_part); // properties that work on all windows if (entry) { // ReadOnlyPart first switch(entry->value) { case Closed: case _Location: // No isSafeScript test here, we must be able to _set_ location.href (#49819) case _Window: case Self: getSlotFromEntry(entry, this, slot); return true; default: break; } if (!part) { slot.setUndefined(this); return true; } // KHTMLPart next switch(entry->value) { case Frames: case Opener: case Parent: case Top: case Alert: case Confirm: case Prompt: case Open: case Close: case Focus: case Blur: case AToB: case BToA: case ValueOf: case ToString: getSlotFromEntry(entry, this, slot); return true; default: break; } } else if (!part) { // not a KHTMLPart QString rvalue; KParts::LiveConnectExtension::Type rtype; unsigned long robjid; if (m_frame->m_liveconnect && isSafeScript(exec) && m_frame->m_liveconnect->get(0, propertyName.qstring(), rtype, robjid, rvalue)) return getImmediateValueSlot(this, getLiveConnectValue(m_frame->m_liveconnect, propertyName.qstring(), rtype, rvalue, robjid), slot); slot.setUndefined(this); return true; } // properties that only work on safe windows - we can handle them now.. if (isSafeScript(exec) && entry) { // Disabled in NS-compat mode. Supported by default - can't hurt, unless someone uses // if (navigate) to test for IE (unlikely). if (entry->value == Navigate && exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat ) { slot.setUndefined(this); return true; } getSlotFromEntry(entry, this, slot); return true; } KParts::ReadOnlyPart *rop = part->findFramePart( propertyName.qstring() ); if (rop) { slot.setCustom(this, framePartGetter); return true; } // allow window[1] or parent[1] etc. (#56983) bool ok; unsigned int i = propertyName.toArrayIndex(&ok); if (ok && frameByIndex(i)) { slot.setCustomIndex(this, i, indexGetterAdapter); return true; } // allow shortcuts like 'Image1' instead of document.images.Image1 DOM::DocumentImpl *doc = part->xmlDocImpl(); if (isSafeScript(exec) && doc && doc->isHTMLDocument()) { DOM::ElementMappingCache::ItemInfo* info = doc ->underDocNamedCache().get(propertyName.qstring()); if (info || doc->getElementById(propertyName.domString())) { slot.setCustom(this, namedItemGetter); return true; } } // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1 // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping. #ifdef KJS_VERBOSE kDebug(6070) << "WARNING: Window::get property not found: " << propertyName.qstring(); #endif return JSObject::getOwnPropertySlot(exec, propertyName, slot); } KParts::ReadOnlyPart* Window::frameByIndex(unsigned i) { KHTMLPart *part = qobject_cast(m_frame->m_part); QList frames = part->frames(); unsigned int len = frames.count(); if (i < len) { KParts::ReadOnlyPart* frame = frames.at(i); return frame; } return 0; } JSValue* Window::indexGetter(ExecState *exec, unsigned index) { KParts::ReadOnlyPart* frame = frameByIndex(index); if (frame) return Window::retrieve(frame); return jsUndefined(); //### ? } JSValue *Window::framePartGetter(ExecState *exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot) { Window* thisObj = static_cast(slot.slotBase()); KHTMLPart *part = qobject_cast(thisObj->m_frame->m_part); KParts::ReadOnlyPart *rop = part->findFramePart( propertyName.qstring() ); return thisObj->retrieve(rop); } JSValue *Window::namedItemGetter(ExecState *exec, JSObject*, const Identifier& p, const PropertySlot& slot) { Window* thisObj = static_cast(slot.slotBase()); KHTMLPart *part = qobject_cast(thisObj->m_frame->m_part); DOM::DocumentImpl* doc = part->xmlDocImpl(); DOM::ElementMappingCache::ItemInfo* info = doc->underDocNamedCache().get(p.qstring()); if (info) { if (info->nd) return getDOMNode(exec, info->nd); else { //No cached mapping, do it by hand... DOM::HTMLMappedNameCollectionImpl* coll = new DOM::HTMLMappedNameCollectionImpl(doc, DOM::HTMLCollectionImpl::DOCUMENT_NAMED_ITEMS, p.domString()); if (coll->length() == 1) { info->nd = static_cast(coll->firstItem()); delete coll; return getDOMNode(exec, info->nd); } return getHTMLCollection(exec, coll); } } DOM::ElementImpl* element = doc->getElementById(p.domString()); return getDOMNode(exec, element); } JSValue* Window::getValueProperty(ExecState *exec, int token) const { KHTMLPart *part = m_frame.isNull() ? 0 : qobject_cast(m_frame->m_part); if (!part) { switch (token) { case Closed: return jsBoolean(true); case _Location: return jsNull(); default: return jsUndefined(); } } switch(token) { case Closed: return jsBoolean(!part); case _Location: // No isSafeScript test here, we must be able to _set_ location.href (#49819) return location(); case _Window: case Self: return retrieve(part); case Frames: return frames(exec); case Opener: if (!part->opener()) return jsNull(); // ### a null Window might be better, but == null else // doesn't work yet return retrieve(part->opener()); case Parent: return retrieve(part && part->parentPart() ? part->parentPart() : (KHTMLPart*)part); case Top: { KHTMLPart *p = part; while (p->parentPart()) p = p->parentPart(); return retrieve(p); } case Crypto: return jsUndefined(); // ### case DefaultStatus: return jsString(UString(part->jsDefaultStatusBarText())); case Status: return jsString(UString(part->jsStatusBarText())); case Document: if (part->document().isNull()) { kDebug(6070) << "Document.write: adding to create document"; part->begin(); part->write(""); part->end(); } return getDOMNode(exec,part->document().handle()); case FrameElement: if (m_frame->m_partContainerElement) return getDOMNode(exec,m_frame->m_partContainerElement); else return jsUndefined(); case Node: return NodeConstructor::self(exec); case Range: return getRangeConstructor(exec); case NodeFilter: return getNodeFilterConstructor(exec); case DOMException: return getDOMExceptionConstructor(exec); case RangeException: return RangeExceptionPseudoCtor::self(exec); case CSSRule: return getCSSRuleConstructor(exec); case ElementCtor: return ElementPseudoCtor::self(exec); case HTMLElementCtor: return HTMLElementPseudoCtor::self(exec); case HTMLHtmlElementCtor: return HTMLHtmlElementPseudoCtor::self(exec); case HTMLHeadElementCtor: return HTMLHeadElementPseudoCtor::self(exec); case HTMLLinkElementCtor: return HTMLLinkElementPseudoCtor::self(exec); case HTMLTitleElementCtor: return HTMLTitleElementPseudoCtor::self(exec); case HTMLMetaElementCtor: return HTMLMetaElementPseudoCtor::self(exec); case HTMLBaseElementCtor: return HTMLBaseElementPseudoCtor::self(exec); case HTMLIsIndexElementCtor: return HTMLIsIndexElementPseudoCtor::self(exec); case HTMLStyleElementCtor: return HTMLStyleElementPseudoCtor::self(exec); case HTMLBodyElementCtor: return HTMLBodyElementPseudoCtor::self(exec); case HTMLFormElementCtor: return HTMLFormElementPseudoCtor::self(exec); case HTMLSelectElementCtor: return HTMLSelectElementPseudoCtor::self(exec); case HTMLOptGroupElementCtor: return HTMLOptGroupElementPseudoCtor::self(exec); case HTMLOptionElementCtor: return HTMLOptionElementPseudoCtor::self(exec); case HTMLInputElementCtor: return HTMLInputElementPseudoCtor::self(exec); case HTMLTextAreaElementCtor: return HTMLTextAreaElementPseudoCtor::self(exec); case HTMLButtonElementCtor: return HTMLButtonElementPseudoCtor::self(exec); case HTMLLabelElementCtor: return HTMLLabelElementPseudoCtor::self(exec); case HTMLFieldSetElementCtor: return HTMLFieldSetElementPseudoCtor::self(exec); case HTMLLegendElementCtor: return HTMLLegendElementPseudoCtor::self(exec); case HTMLUListElementCtor: return HTMLUListElementPseudoCtor::self(exec); case HTMLOListElementCtor: return HTMLOListElementPseudoCtor::self(exec); case HTMLDListElementCtor: return HTMLDListElementPseudoCtor::self(exec); case HTMLDirectoryElementCtor: return HTMLDirectoryElementPseudoCtor::self(exec); case HTMLMenuElementCtor: return HTMLMenuElementPseudoCtor::self(exec); case HTMLLIElementCtor: return HTMLLIElementPseudoCtor::self(exec); case HTMLDivElementCtor: return HTMLDivElementPseudoCtor::self(exec); case HTMLParagraphElementCtor: return HTMLParagraphElementPseudoCtor::self(exec); case HTMLHeadingElementCtor: return HTMLHeadingElementPseudoCtor::self(exec); case HTMLBlockQuoteElementCtor: return HTMLBlockQuoteElementPseudoCtor::self(exec); case HTMLQuoteElementCtor: return HTMLQuoteElementPseudoCtor::self(exec); case HTMLPreElementCtor: return HTMLPreElementPseudoCtor::self(exec); case HTMLBRElementCtor: return HTMLBRElementPseudoCtor::self(exec); case HTMLBaseFontElementCtor: return HTMLBaseFontElementPseudoCtor::self(exec); case HTMLFontElementCtor: return HTMLFontElementPseudoCtor::self(exec); case HTMLHRElementCtor: return HTMLHRElementPseudoCtor::self(exec); case HTMLModElementCtor: return HTMLModElementPseudoCtor::self(exec); case HTMLAnchorElementCtor: return HTMLAnchorElementPseudoCtor::self(exec); case HTMLImageElementCtor: return HTMLImageElementPseudoCtor::self(exec); case HTMLObjectElementCtor: return HTMLObjectElementPseudoCtor::self(exec); case HTMLParamElementCtor: return HTMLParamElementPseudoCtor::self(exec); case HTMLAppletElementCtor: return HTMLAppletElementPseudoCtor::self(exec); case HTMLMapElementCtor: return HTMLMapElementPseudoCtor::self(exec); case HTMLAreaElementCtor: return HTMLAreaElementPseudoCtor::self(exec); case HTMLScriptElementCtor: return HTMLScriptElementPseudoCtor::self(exec); case HTMLTableElementCtor: return HTMLTableElementPseudoCtor::self(exec); case HTMLTableCaptionElementCtor: return HTMLTableCaptionElementPseudoCtor::self(exec); case HTMLTableColElementCtor: return HTMLTableColElementPseudoCtor::self(exec); case HTMLTableSectionElementCtor: return HTMLTableSectionElementPseudoCtor::self(exec); case HTMLTableRowElementCtor: return HTMLTableRowElementPseudoCtor::self(exec); case HTMLTableCellElementCtor: return HTMLTableCellElementPseudoCtor::self(exec); case HTMLFrameSetElementCtor: return HTMLFrameSetElementPseudoCtor::self(exec); case HTMLLayerElementCtor: return HTMLLayerElementPseudoCtor::self(exec); case HTMLFrameElementCtor: return HTMLFrameElementPseudoCtor::self(exec); case HTMLIFrameElementCtor: return HTMLIFrameElementPseudoCtor::self(exec); case HTMLCanvasElementCtor: return HTMLCanvasElementPseudoCtor::self(exec); case Context2DCtor: return Context2DPseudoCtor::self(exec); case DocumentCtor: return DocumentPseudoCtor::self(exec); case HTMLDocumentCtor: return HTMLDocumentPseudoCtor::self(exec); case CSSStyleDeclarationCtor: return CSSStyleDeclarationPseudoCtor::self(exec); case EventCtor: return EventConstructor::self(exec); case MutationEventCtor: return getMutationEventConstructor(exec); case KeyboardEventCtor: return getKeyboardEventConstructor(exec); case EventExceptionCtor: return getEventExceptionConstructor(exec); case _History: return history ? history : (const_cast(this)->history = new History(exec,part)); case _External: return external ? external : (const_cast(this)->external = new External(exec,part)); case Event: if (m_evt) return getDOMEvent(exec,m_evt); else { #ifdef KJS_VERBOSE kDebug(6070) << "WARNING: window(" << this << "," << part->objectName() << ").event, no event!"; #endif return jsUndefined(); } case InnerHeight: { if (!part->view()) return jsUndefined(); khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size int ret = part->view()->visibleHeight(); // match Gecko which does not subtract the scrollbars if (part->view()->horizontalScrollBar()->isVisible()) { ret += part->view()->style()->pixelMetric(QStyle::PM_ScrollBarExtent); int lvs = part->view()->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing); if (lvs > 0) ret += lvs; } return jsNumber(ret); } case InnerWidth: { if (!part->view()) return jsUndefined(); khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size int ret = part->view()->visibleWidth(); // match Gecko which does not subtract the scrollbars if (part->view()->verticalScrollBar()->isVisible()) { ret += part->view()->style()->pixelMetric(QStyle::PM_ScrollBarExtent); int lhs = part->view()->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); if (lhs > 0) ret += lhs; } return jsNumber(ret); } case Length: return jsNumber(part->frames().count()); case Name: return jsString(part->objectName()); case SideBar: return new MozillaSidebarExtension(exec, part); case _Navigator: case ClientInformation: { // Store the navigator in the object so we get the same one each time. JSValue *nav( new Navigator(exec, part) ); const_cast(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal); const_cast(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal); return nav; } case OffscreenBuffering: return jsBoolean(true); case OuterHeight: case OuterWidth: { #if defined Q_WS_X11 && ! defined K_WS_QTONLY if (!part->widget()) return jsNumber(0); KWindowInfo inf = KWindowSystem::windowInfo(part->widget()->topLevelWidget()->winId(), NET::WMGeometry); return jsNumber(token == OuterHeight ? inf.geometry().height() : inf.geometry().width()); #else return jsNumber(token == OuterHeight ? part->view()->height() : part->view()->width()); #endif } case PageXOffset: return jsNumber(part->view()->contentsX()); case PageYOffset: return jsNumber(part->view()->contentsY()); case Personalbar: return jsUndefined(); // ### case ScreenLeft: case ScreenX: { if (!part->view()) return jsUndefined(); QRect sg = KGlobalSettings::desktopGeometry(part->view()); return jsNumber(part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x()); } case ScreenTop: case ScreenY: { if (!part->view()) return jsUndefined(); QRect sg = KGlobalSettings::desktopGeometry(part->view()); return jsNumber(part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y()); } case ScrollX: { if (!part->view()) return jsUndefined(); return jsNumber(part->view()->contentsX()); } case ScrollY: { if (!part->view()) return jsUndefined(); return jsNumber(part->view()->contentsY()); } case Scrollbars: return jsUndefined(); // ### case _Screen: return screen ? screen : (const_cast(this)->screen = new Screen(exec)); case Audio: return new AudioConstructorImp(exec, part->xmlDocImpl()); case Image: return new ImageConstructorImp(exec, part->xmlDocImpl()); case Option: return new OptionConstructorImp(exec, part->xmlDocImpl()); case XMLHttpRequest: return new XMLHttpRequestConstructorImp(exec, part->xmlDocImpl()); case XMLSerializer: return new XMLSerializerConstructorImp(exec); case DOMParser: return new DOMParserConstructorImp(exec, part->xmlDocImpl()); case Onabort: return getListener(exec,DOM::EventImpl::ABORT_EVENT); case Onblur: return getListener(exec,DOM::EventImpl::BLUR_EVENT); case Onchange: return getListener(exec,DOM::EventImpl::CHANGE_EVENT); case Onclick: return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT); case Ondblclick: return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT); case Ondragdrop: return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT); case Onerror: return getListener(exec,DOM::EventImpl::ERROR_EVENT); case Onfocus: return getListener(exec,DOM::EventImpl::FOCUS_EVENT); case Onkeydown: return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT); case Onkeypress: return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT); case Onkeyup: return getListener(exec,DOM::EventImpl::KEYUP_EVENT); case Onload: return getListener(exec,DOM::EventImpl::LOAD_EVENT); case Onmousedown: return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT); case Onmousemove: return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT); case Onmouseout: return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT); case Onmouseover: return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT); case Onmouseup: return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT); case Onmove: return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT); case Onreset: return getListener(exec,DOM::EventImpl::RESET_EVENT); case Onresize: return getListener(exec,DOM::EventImpl::RESIZE_EVENT); case Onselect: return getListener(exec,DOM::EventImpl::SELECT_EVENT); case Onsubmit: return getListener(exec,DOM::EventImpl::SUBMIT_EVENT); case Onunload: return getListener(exec,DOM::EventImpl::UNLOAD_EVENT); } return jsUndefined(); } void Window::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr) { // we don't want any operations on a closed window if (m_frame.isNull() || m_frame->m_part.isNull()) { // ### throw exception? allow setting of some props like location? return; } // Called by an internal KJS call (e.g. InterpreterImp's constructor) ? // If yes, save time and jump directly to JSObject. if ( (attr != None && attr != DontDelete) || // Same thing if we have a local override (e.g. "var location") ( isSafeScript( exec ) && JSObject::getDirect(propertyName) ) ) { JSObject::put( exec, propertyName, value, attr ); return; } const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName); if (entry && !m_frame.isNull() && !m_frame->m_part.isNull()) { #ifdef KJS_VERBOSE kDebug(6070) << "Window("<value) { case _Location: goURL(exec, value->toString(exec).qstring(), false /*don't lock history*/); return; default: break; } KHTMLPart *part = qobject_cast(m_frame->m_part); if (part) { switch( entry->value ) { case Status: { if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host()) == KHTMLSettings::KJSWindowStatusAllow) { UString s = value->toString(exec); part->setJSStatusBarText(s.qstring()); } return; } case DefaultStatus: { if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host()) == KHTMLSettings::KJSWindowStatusAllow) { UString s = value->toString(exec); part->setJSDefaultStatusBarText(s.qstring()); } return; } case Onabort: if (isSafeScript(exec)) setListener(exec, DOM::EventImpl::ABORT_EVENT,value); return; case Onblur: if (isSafeScript(exec)) setListener(exec, DOM::EventImpl::BLUR_EVENT,value); return; case Onchange: if (isSafeScript(exec)) setListener(exec, DOM::EventImpl::CHANGE_EVENT,value); return; case Onclick: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value); return; case Ondblclick: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value); return; case Ondragdrop: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value); return; case Onerror: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::ERROR_EVENT,value); return; case Onfocus: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::FOCUS_EVENT,value); return; case Onkeydown: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value); return; case Onkeypress: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value); return; case Onkeyup: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::KEYUP_EVENT,value); return; case Onload: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::LOAD_EVENT,value); return; case Onmousedown: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value); return; case Onmousemove: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value); return; case Onmouseout: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value); return; case Onmouseover: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value); return; case Onmouseup: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value); return; case Onmove: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value); return; case Onreset: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::RESET_EVENT,value); return; case Onresize: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::RESIZE_EVENT,value); return; case Onselect: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::SELECT_EVENT,value); return; case Onsubmit: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value); return; case Onunload: if (isSafeScript(exec)) setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value); return; case Name: if (isSafeScript(exec)) part->setObjectName( value->toString(exec).qstring().toLocal8Bit().data() ); return; default: break; } } } if (m_frame->m_liveconnect && isSafeScript(exec) && m_frame->m_liveconnect->put(0, propertyName.qstring(), value->toString(exec).qstring())) return; if (isSafeScript(exec)) { //kDebug(6070) << "Window("<m_part.isNull(); } DOM::AbstractViewImpl* Window::toAbstractView() const { KHTMLPart *part = ::qobject_cast(m_frame->m_part); if (!part || !part->xmlDocImpl()) return 0; return part->xmlDocImpl()->defaultView(); } void Window::scheduleClose() { kDebug(6070) << "Window::scheduleClose window.close() " << m_frame; Q_ASSERT(winq); QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) ); } void Window::closeNow() { if (m_frame.isNull() || m_frame->m_part.isNull()) { kDebug(6070) << "part is deleted already"; } else { KHTMLPart *part = qobject_cast(m_frame->m_part); if (!part) { kDebug(6070) << "closeNow on non KHTML part"; } else { //kDebug(6070) << " -> closing window"; // We want to make sure that window.open won't find this part by name. part->setObjectName( QString() ); part->deleteLater(); part = 0; } } } void Window::afterScriptExecution() { DOM::DocumentImpl::updateDocumentsRendering(); QList delayedActions = m_delayed; m_delayed.clear(); QList::Iterator it = delayedActions.begin(); for ( ; it != delayedActions.end() ; ++it ) { switch ((*it).actionId) { case DelayedClose: scheduleClose(); return; // stop here, in case of multiple actions case DelayedGoHistory: goHistory( (*it).param.toInt() ); break; case NullAction: // FIXME: anything needs to be done here? This is warning anyways. break; }; } } bool Window::checkIsSafeScript(KParts::ReadOnlyPart *activePart) const { if (m_frame.isNull() || m_frame->m_part.isNull()) { // part deleted ? can't grant access kDebug(6070) << "Window::isSafeScript: accessing deleted part !"; return false; } if (!activePart) { kDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!"; return false; } if ( activePart == m_frame->m_part ) // Not calling from another frame, no problem. return true; KHTMLPart *part = qobject_cast(m_frame->m_part); if (!part) return true; // not a KHTMLPart if ( part->document().isNull() ) return true; // allow to access a window that was just created (e.g. with window.open("about:blank")) DOM::HTMLDocument thisDocument = part->htmlDocument(); if ( thisDocument.isNull() ) { kDebug(6070) << "Window::isSafeScript: trying to access an XML document !?"; return false; } KHTMLPart *activeKHTMLPart = qobject_cast(activePart); if (!activeKHTMLPart) return true; // not a KHTMLPart DOM::HTMLDocument actDocument = activeKHTMLPart->htmlDocument(); if ( actDocument.isNull() ) { kDebug(6070) << "Window::isSafeScript: active part has no document!"; return false; } DOM::DOMString actDomain = actDocument.domain(); DOM::DOMString thisDomain = thisDocument.domain(); if ( actDomain == thisDomain ) { #ifdef KJS_VERBOSE //kDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'"; #endif return true; } kDebug(6070) << "WARNING: JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'"; // TODO after 3.1: throw security exception (exec->setException()) return false; } void Window::setListener(ExecState *exec, int eventId, JSValue *func) { KHTMLPart *part = qobject_cast(m_frame->m_part); if (!part || !isSafeScript(exec)) return; DOM::DocumentImpl *doc = static_cast(part->htmlDocument().handle()); if (!doc) return; doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true)); } JSValue *Window::getListener(ExecState *exec, int eventId) const { KHTMLPart *part = qobject_cast(m_frame->m_part); if (!part || !isSafeScript(exec)) return jsUndefined(); DOM::DocumentImpl *doc = static_cast(part->htmlDocument().handle()); if (!doc) return jsUndefined(); DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId); if (listener && static_cast(listener)->listenerObj()) return static_cast(listener)->listenerObj(); else return jsNull(); } JSEventListener *Window::getJSEventListener(JSValue *val, bool html) { // This function is so hot that it's worth coding it directly with imps. KHTMLPart *part = qobject_cast(m_frame->m_part); if (!part || val->type() != ObjectType) return 0; // It's ObjectType, so it must be valid. JSObject *listenerObject = val->getObject(); // 'listener' is not a simple ecma function. (Always use sanity checks: Better safe than sorry!) if (!listenerObject->implementsCall() && part && part->jScript() && part->jScript()->interpreter()) { Interpreter *interpreter = part->jScript()->interpreter(); // 'listener' probably is an EventListener object containing a 'handleEvent' function. JSValue *handleEventValue = listenerObject->get(interpreter->globalExec(), Identifier("handleEvent")); JSObject *handleEventObject = handleEventValue->getObject(); if(handleEventObject && handleEventObject->implementsCall()) { listenerObject = handleEventObject; } } JSEventListener *existingListener = jsEventListeners[listenerObject]; if (existingListener) { if ( existingListener->isHTMLEventListener() != html ) // The existingListener will have the wrong type, so onclick= will behave like addEventListener or vice versa. kWarning() << "getJSEventListener: event listener already found but with html=" << !html << " - please report this, we thought it would never happen"; return existingListener; } // Note that the JSEventListener constructor adds it to our jsEventListeners list return new JSEventListener(listenerObject, listenerObject, this, html); } JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, const QString& srcUrl, int line, const QString& name, DOM::NodeImpl *node) { return new JSLazyEventListener(code, srcUrl, line, name, this, node); } void Window::clear( ExecState *exec ) { delete winq; winq = 0L; // Get rid of everything, those user vars could hold references to DOM nodes clearProperties(); // Break the dependency between the listeners and their object QHashIterator it(jsEventListeners); while ( it.hasNext() ) { it.next(); it.value()->clear(); } // Forget about the listeners (the DOM::NodeImpls will delete them) jsEventListeners.clear(); if (m_frame) { KJSProxy* proxy = m_frame->m_jscript; if (proxy) // i.e. JS not disabled { winq = new WindowQObject(this); // Now recreate a working global object for the next URL that will use us KJS::Interpreter *interpreter = proxy->interpreter(); interpreter->initGlobalObject(); } } } void Window::setCurrentEvent( DOM::EventImpl *evt ) { m_evt = evt; //kDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt; } void Window::goURL(ExecState* exec, const QString& url, bool lockHistory) { Window* active = Window::retrieveActive(exec); KHTMLPart *part = qobject_cast(m_frame->m_part); KHTMLPart *active_part = qobject_cast(active->part()); // Complete the URL using the "active part" (running interpreter) if (active_part && part) { if (url[0] == QChar('#')) { part->gotoAnchor(url.mid(1)); } else { QString dstUrl = active_part->htmlDocument().completeURL(url).string(); kDebug(6070) << "Window::goURL dstUrl=" << dstUrl; // check if we're allowed to inject javascript // SYNC check with khtml_part.cpp::slotRedirect! if ( isSafeScript(exec) || dstUrl.indexOf(QLatin1String("javascript:"), 0, Qt::CaseInsensitive) != 0 ) part->scheduleRedirection(-1, dstUrl, lockHistory); } } else if (!part && m_frame->m_partContainerElement) { KParts::BrowserExtension *b = KParts::BrowserExtension::childObject(m_frame->m_part); if (b) emit b->openUrlRequest(m_frame->m_partContainerElement->getDocument()->completeURL(url)); kDebug() << "goURL for ROPart"; } } void Window::delayedGoHistory( int steps ) { m_delayed.append( DelayedAction( DelayedGoHistory, steps ) ); } void Window::goHistory( int steps ) { KHTMLPart *part = qobject_cast(m_frame->m_part); if(!part) // TODO history readonlypart return; KParts::BrowserExtension *ext = part->browserExtension(); if(!ext) return; KParts::BrowserInterface *iface = ext->browserInterface(); if ( !iface ) return; iface->callMethod( "goHistory(int)", steps ); //emit ext->goHistory(steps); } void KJS::Window::resizeTo(QWidget* tl, int width, int height) { KHTMLPart *part = qobject_cast(m_frame->m_part); if(!part) // TODO resizeTo readonlypart return; KParts::BrowserExtension *ext = part->browserExtension(); if (!ext) { kDebug(6070) << "Window::resizeTo found no browserExtension"; return; } // Security check: within desktop limits and bigger than 100x100 (per spec) if ( width < 100 || height < 100 ) { kDebug(6070) << "Window::resizeTo refused, window would be too small ("< sg.width() || height > sg.height() ) { kDebug(6070) << "Window::resizeTo refused, window would be too big ("<resizeTopLevelWidget( width, height ); // If the window is out of the desktop, move it up/left // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker) int right = tl->x() + tl->frameGeometry().width(); int bottom = tl->y() + tl->frameGeometry().height(); int moveByX = 0; int moveByY = 0; if ( right > sg.right() ) moveByX = - right + sg.right(); // always <0 if ( bottom > sg.bottom() ) moveByY = - bottom + sg.bottom(); // always <0 if ( moveByX || moveByY ) emit ext->moveTopLevelWidget( tl->x() + moveByX , tl->y() + moveByY ); } JSValue *Window::openWindow(ExecState *exec, const List& args) { KHTMLPart *part = qobject_cast(m_frame->m_part); if (!part) return jsUndefined(); KHTMLView *widget = part->view(); JSValue *v = args[0]; QString str; if (!v->isUndefinedOrNull()) str = v->toString(exec).qstring(); // prepare arguments KUrl url; if (!str.isEmpty()) { KHTMLPart* p = qobject_cast(Window::retrieveActive(exec)->m_frame->m_part); if ( p ) url = p->htmlDocument().completeURL(str).string(); if ( !p || !static_cast(p->htmlDocument().handle())->isURLAllowed(url.url()) ) return jsUndefined(); } KHTMLSettings::KJSWindowOpenPolicy policy = part->settings()->windowOpenPolicy(part->url().host()); if ( policy == KHTMLSettings::KJSWindowOpenAsk ) { emit part->browserExtension()->requestFocus(part); QString caption; if (!part->url().host().isEmpty()) caption = part->url().host() + " - "; caption += i18n( "Confirmation: JavaScript Popup" ); if ( KMessageBox::questionYesNo(widget, str.isEmpty() ? i18n( "This site is requesting to open up a new browser " "window via JavaScript.\n" "Do you want to allow this?" ) : i18n( "This site is requesting to open

%1

in a new browser window via JavaScript.
" "Do you want to allow this?
", KStringHandler::csqueeze(Qt::escape(url.prettyUrl()), 100)), caption, KGuiItem(i18n("Allow")), KGuiItem(i18n("Do Not Allow")) ) == KMessageBox::Yes ) policy = KHTMLSettings::KJSWindowOpenAllow; } else if ( policy == KHTMLSettings::KJSWindowOpenSmart ) { // window.open disabled unless from a key/mouse event if (static_cast(exec->dynamicInterpreter())->isWindowOpenAllowed()) policy = KHTMLSettings::KJSWindowOpenAllow; } QString frameName = args.size() > 1 ? args[1]->toString(exec).qstring() : QString("_blank"); v = args[2]; QString features; if (v && v->type() != UndefinedType && v->toString(exec).size() > 0) { features = v->toString(exec).qstring(); // Buggy scripts have ' at beginning and end, cut those if (features.startsWith("\'") && features.endsWith("\'")) features = features.mid(1, features.length()-2); } if ( policy != KHTMLSettings::KJSWindowOpenAllow ) { if ( url.isEmpty() ) part->setSuppressedPopupIndicator(true, 0); else { part->setSuppressedPopupIndicator(true, part); m_suppressedWindowInfo.append( SuppressedWindowInfo( url, frameName, features ) ); } return jsUndefined(); } else { return executeOpenWindow(exec, url, frameName, features); } } JSValue *Window::executeOpenWindow(ExecState *exec, const KUrl& url, const QString& frameName, const QString& features) { KHTMLPart *p = qobject_cast(m_frame->m_part); KHTMLView *widget = p->view(); KParts::WindowArgs winargs; // scan feature argument if (!features.isEmpty()) { // specifying window params means false defaults winargs.setMenuBarVisible(false); winargs.setToolBarsVisible(false); winargs.setStatusBarVisible(false); winargs.setScrollBarsVisible(false); QStringList flist = features.split(','); QStringList::ConstIterator it = flist.begin(); while (it != flist.end()) { QString s = *it++; QString key, val; int pos = s.indexOf('='); if (pos >= 0) { key = s.left(pos).trimmed().toLower(); val = s.mid(pos + 1).trimmed().toLower(); QRect screen = KGlobalSettings::desktopGeometry(widget->topLevelWidget()); if (key == "left" || key == "screenx") { winargs.setX((int)val.toFloat() + screen.x()); if (winargs.x() < screen.x() || winargs.x() > screen.right()) winargs.setX(screen.x()); // only safe choice until size is determined } else if (key == "top" || key == "screeny") { winargs.setY((int)val.toFloat() + screen.y()); if (winargs.y() < screen.y() || winargs.y() > screen.bottom()) winargs.setY(screen.y()); // only safe choice until size is determined } else if (key == "height") { winargs.setHeight((int)val.toFloat() + 2*qApp->style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2); if (winargs.height() > screen.height()) // should actually check workspace winargs.setHeight(screen.height()); if (winargs.height() < 100) winargs.setHeight(100); } else if (key == "width") { winargs.setWidth((int)val.toFloat() + 2*qApp->style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2); if (winargs.width() > screen.width()) // should actually check workspace winargs.setWidth(screen.width()); if (winargs.width() < 100) winargs.setWidth(100); } else { goto boolargs; } continue; } else { // leaving away the value gives true key = s.trimmed().toLower(); val = "1"; } boolargs: if (key == "menubar") winargs.setMenuBarVisible(val == "1" || val == "yes"); else if (key == "toolbar") winargs.setToolBarsVisible(val == "1" || val == "yes"); else if (key == "location") // ### missing in WindowArgs winargs.setToolBarsVisible(val == "1" || val == "yes"); else if (key == "status" || key == "statusbar") winargs.setStatusBarVisible(val == "1" || val == "yes"); else if (key == "scrollbars") winargs.setScrollBarsVisible(val == "1" || val == "yes"); else if (key == "resizable") winargs.setResizable(val == "1" || val == "yes"); else if (key == "fullscreen") winargs.setFullScreen(val == "1" || val == "yes"); } } KParts::OpenUrlArguments args; KParts::BrowserArguments browserArgs; browserArgs.frameName = frameName; if ( browserArgs.frameName.toLower() == "_top" ) { while ( p->parentPart() ) p = p->parentPart(); Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/); return Window::retrieve(p); } if ( browserArgs.frameName.toLower() == "_parent" ) { if ( p->parentPart() ) p = p->parentPart(); Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/); return Window::retrieve(p); } if ( browserArgs.frameName.toLower() == "_self") { Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/); return Window::retrieve(p); } if ( browserArgs.frameName.toLower() == "replace" ) { Window::retrieveWindow(p)->goURL(exec, url.url(), true /*lock history*/); return Window::retrieve(p); } args.setMimeType("text/html"); // request window (new or existing if framename is set) KParts::ReadOnlyPart *newPart = 0; emit p->browserExtension()->createNewWindow(KUrl(), args, browserArgs, winargs, &newPart); if (newPart && qobject_cast(newPart)) { KHTMLPart *khtmlpart = static_cast(newPart); //qDebug("opener set to %p (this Window's part) in new Window %p (this Window=%p)",part,win,window); khtmlpart->setOpener(p); khtmlpart->setOpenedByJS(true); if (khtmlpart->document().isNull()) { khtmlpart->begin(); khtmlpart->write(""); khtmlpart->end(); if ( p->docImpl() ) { //kDebug(6070) << "Setting domain to " << p->docImpl()->domain().string(); khtmlpart->docImpl()->setDomain( p->docImpl()->domain()); khtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() ); } } args.setMimeType(QString()); if (browserArgs.frameName.toLower() == "_blank") browserArgs.frameName.clear(); if (!url.isEmpty()) emit khtmlpart->browserExtension()->openUrlRequest(url, args, browserArgs); return Window::retrieve(khtmlpart); // global object } else return jsUndefined(); } void Window::forgetSuppressedWindows() { m_suppressedWindowInfo.clear(); } void Window::showSuppressedWindows() { KHTMLPart *part = qobject_cast(m_frame->m_part); KJS::Interpreter *interpreter = part->jScript()->interpreter(); ExecState *exec = interpreter->globalExec(); QList suppressedWindowInfo = m_suppressedWindowInfo; m_suppressedWindowInfo.clear(); foreach ( SuppressedWindowInfo info, suppressedWindowInfo ) { executeOpenWindow(exec, info.url, info.frameName, info.features); } } JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { KJS_CHECK_THIS( Window, thisObj ); // these should work no matter whether the window is already // closed or not if (id == Window::ValueOf || id == Window::ToString) { return jsString("[object Window]"); } Window *window = static_cast(thisObj); QString str, str2; KHTMLPart *part = qobject_cast(window->m_frame->m_part); if (!part) return jsUndefined(); KHTMLView *widget = part->view(); JSValue *v = args[0]; UString s; if (!v->isUndefinedOrNull()) { s = v->toString(exec); str = s.qstring(); } QString caption; if (part && !part->url().host().isEmpty()) caption = part->url().host() + " - "; caption += "JavaScript"; // TODO: i18n // functions that work everywhere switch(id) { case Window::Alert: { TimerPauser pause(exec); if (!widget->dialogsAllowed()) return jsUndefined(); if ( part && part->xmlDocImpl() ) part->xmlDocImpl()->updateRendering(); if ( part ) emit part->browserExtension()->requestFocus(part); KMessageBox::error(widget, Qt::convertFromPlainText(str, Qt::WhiteSpaceNormal), caption); return jsUndefined(); } case Window::Confirm: { TimerPauser pause(exec); if (!widget->dialogsAllowed()) return jsUndefined(); if ( part && part->xmlDocImpl() ) part->xmlDocImpl()->updateRendering(); if ( part ) emit part->browserExtension()->requestFocus(part); return jsBoolean((KMessageBox::warningYesNo(widget, Qt::convertFromPlainText(str), caption, KStandardGuiItem::ok(), KStandardGuiItem::cancel()) == KMessageBox::Yes)); } case Window::Prompt: { TimerPauser pause(exec); #ifndef KONQ_EMBEDDED if (!widget->dialogsAllowed()) return jsUndefined(); if ( part && part->xmlDocImpl() ) part->xmlDocImpl()->updateRendering(); if ( part ) emit part->browserExtension()->requestFocus(part); bool ok; if (args.size() >= 2) str2 = KInputDialog::getText(caption, Qt::convertFromPlainText(str), args[1]->toString(exec).qstring(), &ok, widget); else str2 = KInputDialog::getText(caption, Qt::convertFromPlainText(str), QString(), &ok, widget); if ( ok ) return jsString(UString(str2)); else return jsNull(); #else return jsUndefined(); #endif } case Window::GetComputedStyle: { if ( !part || !part->xmlDocImpl() ) return jsUndefined(); DOM::NodeImpl* arg0 = toNode(args[0]); if (!arg0 || arg0->nodeType() != DOM::Node::ELEMENT_NODE) return jsUndefined(); // throw exception? else return getDOMCSSStyleDeclaration(exec, part->xmlDocImpl()->defaultView()->getComputedStyle( static_cast(arg0), args[1]->toString(exec).domString().implementation())); } case Window::Open: return window->openWindow(exec, args); case Window::Close: { /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm : The close method closes only windows opened by JavaScript using the open method. If you attempt to close any other window, a confirm is generated, which lets the user choose whether the window closes. This is a security feature to prevent "mail bombs" containing self.close(). However, if the window has only one document (the current one) in its session history, the close is allowed without any confirm. This is a special case for one-off windows that need to open other windows and then dispose of themselves. */ bool doClose = false; if (!part->openedByJS()) { // To conform to the SPEC, we only ask if the window // has more than one entry in the history (NS does that too). History history(exec,part); if ( history.get( exec, "length" )->toInt32(exec) <= 1 ) { doClose = true; } else { // Can we get this dialog with tabs??? Does it close the window or the tab in that case? emit part->browserExtension()->requestFocus(part); if ( KMessageBox::questionYesNo( window->part()->widget(), i18n("Close window?"), i18n("Confirmation Required"), KStandardGuiItem::close(), KStandardGuiItem::cancel() ) == KMessageBox::Yes ) doClose = true; } } else doClose = true; if (doClose) { // If this is the current window (the one the interpreter runs in), // then schedule a delayed close (so that the script terminates first). // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name"); if ( Window::retrieveActive(exec) == window ) { if (widget) { // quit all dialogs of this view // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash widget->closeChildDialogs(); } //kDebug() << "scheduling delayed close"; // We'll close the window at the end of the script execution Window* w = const_cast(window); w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) ); } else { //kDebug() << "closing NOW"; (const_cast(window))->closeNow(); } } return jsUndefined(); } case Window::Navigate: window->goURL(exec, args[0]->toString(exec).qstring(), false /*don't lock history*/); return jsUndefined(); case Window::Focus: { KHTMLSettings::KJSWindowFocusPolicy policy = part->settings()->windowFocusPolicy(part->url().host()); if(policy == KHTMLSettings::KJSWindowFocusAllow && widget) { widget->topLevelWidget()->raise(); #ifdef Q_WS_X11 KWindowSystem::unminimizeWindow( widget->topLevelWidget()->winId() ); #else //TODO #endif widget->activateWindow(); emit part->browserExtension()->requestFocus(part); } return jsUndefined(); } case Window::Blur: // TODO return jsUndefined(); case Window::BToA: case Window::AToB: { if (!s.is8Bit()) return jsUndefined(); QByteArray in, out; char *binData = s.ascii(); in = QByteArray( binData, s.size() ); if (id == Window::AToB) out = QByteArray::fromBase64(in); else out = in.toBase64(); UChar *d = new UChar[out.size()]; for (int i = 0; i < out.size(); i++) d[i].uc = (uchar) out[i]; UString ret(d, out.size(), false /*no copy*/); return jsString(ret); } }; // now unsafe functions.. if (!window->isSafeScript(exec)) return jsUndefined(); switch (id) { case Window::ScrollBy: if(args.size() == 2 && widget) widget->scrollBy(args[0]->toInt32(exec), args[1]->toInt32(exec)); return jsUndefined(); case Window::Scroll: case Window::ScrollTo: if(args.size() == 2 && widget) widget->setContentsPos(args[0]->toInt32(exec), args[1]->toInt32(exec)); return jsUndefined(); case Window::MoveBy: { KHTMLSettings::KJSWindowMovePolicy policy = part->settings()->windowMovePolicy(part->url().host()); if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget) { KParts::BrowserExtension *ext = part->browserExtension(); if (ext) { QWidget * tl = widget->topLevelWidget(); QRect sg = KGlobalSettings::desktopGeometry(tl); QPoint dest = tl->pos() + QPoint( args[0]->toInt32(exec), args[1]->toInt32(exec) ); // Security check (the spec talks about UniversalBrowserWrite to disable this check...) if ( dest.x() >= sg.x() && dest.y() >= sg.x() && dest.x()+tl->width() <= sg.width()+sg.x() && dest.y()+tl->height() <= sg.height()+sg.y() ) emit ext->moveTopLevelWidget( dest.x(), dest.y() ); } } return jsUndefined(); } case Window::MoveTo: { KHTMLSettings::KJSWindowMovePolicy policy = part->settings()->windowMovePolicy(part->url().host()); if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget) { KParts::BrowserExtension *ext = part->browserExtension(); if (ext) { QWidget * tl = widget->topLevelWidget(); QRect sg = KGlobalSettings::desktopGeometry(tl); QPoint dest( args[0]->toInt32(exec)+sg.x(), args[1]->toInt32(exec)+sg.y() ); // Security check (the spec talks about UniversalBrowserWrite to disable this check...) if ( dest.x() >= sg.x() && dest.y() >= sg.y() && dest.x()+tl->width() <= sg.width()+sg.x() && dest.y()+tl->height() <= sg.height()+sg.y() ) emit ext->moveTopLevelWidget( dest.x(), dest.y() ); } } return jsUndefined(); } case Window::ResizeBy: { KHTMLSettings::KJSWindowResizePolicy policy = part->settings()->windowResizePolicy(part->url().host()); if(policy == KHTMLSettings::KJSWindowResizeAllow && args.size() == 2 && widget) { QWidget * tl = widget->topLevelWidget(); QRect geom = tl->frameGeometry(); window->resizeTo( tl, geom.width() + args[0]->toInt32(exec), geom.height() + args[1]->toInt32(exec) ); } return jsUndefined(); } case Window::ResizeTo: { KHTMLSettings::KJSWindowResizePolicy policy = part->settings()->windowResizePolicy(part->url().host()); if(policy == KHTMLSettings::KJSWindowResizeAllow && args.size() == 2 && widget) { QWidget * tl = widget->topLevelWidget(); window->resizeTo( tl, args[0]->toInt32(exec), args[1]->toInt32(exec) ); } return jsUndefined(); } case Window::SetTimeout: case Window::SetInterval: { bool singleShot; int i; // timeout interval if (args.size() == 0) return jsUndefined(); if (args.size() > 1) { singleShot = (id == Window::SetTimeout); i = args[1]->toInt32(exec); } else { // second parameter is missing. Emulate Mozilla behavior. singleShot = true; i = 4; } if (v->type() == StringType) { int r = (const_cast(window))->winq->installTimeout(Identifier(s), i, singleShot ); return jsNumber(r); } else if (v->type() == ObjectType && v->getObject()->implementsCall()) { JSObject *func = v->getObject(); List funcArgs; ListIterator it = args.begin(); int argno = 0; while (it != args.end()) { JSValue *arg = it++; if (argno++ >= 2) funcArgs.append(arg); } if (args.size() < 2) funcArgs.append(jsNumber(i)); int r = (const_cast(window))->winq->installTimeout(func, funcArgs, i, singleShot ); return jsNumber(r); } else return jsUndefined(); } case Window::ClearTimeout: case Window::ClearInterval: (const_cast(window))->winq->clearTimeout(v->toInt32(exec)); return jsUndefined(); case Window::Print: if ( widget ) { // ### TODO emit onbeforeprint event widget->print(); // ### TODO emit onafterprint event } case Window::CaptureEvents: case Window::ReleaseEvents: // Do nothing for now. These are NS-specific legacy calls. break; case Window::AddEventListener: { JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); if (listener) { DOM::DocumentImpl* docimpl = static_cast(part->document().handle()); docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0]->toString(exec).domString()),listener,args[2]->toBoolean(exec)); } return jsUndefined(); } case Window::RemoveEventListener: { JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); if (listener) { DOM::DocumentImpl* docimpl = static_cast(part->document().handle()); docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0]->toString(exec).domString()),listener,args[2]->toBoolean(exec)); } return jsUndefined(); } } return jsUndefined(); } ////////////////////// ScheduledAction //////////////////////// // KDE 4: Make those parameters const ... & ScheduledAction::ScheduledAction(JSObject* _func, List _args, DateTimeMS _nextTime, int _interval, bool _singleShot, int _timerId) { //kDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this; func = static_cast(_func); args = _args; isFunction = true; singleShot = _singleShot; nextTime = _nextTime; interval = _interval; executing = false; timerId = _timerId; } // KDE 4: Make it const QString & ScheduledAction::ScheduledAction(QString _code, DateTimeMS _nextTime, int _interval, bool _singleShot, int _timerId) { //kDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this; //func = 0; //args = 0; func = 0; code = _code; isFunction = false; singleShot = _singleShot; nextTime = _nextTime; interval = _interval; executing = false; timerId = _timerId; } bool ScheduledAction::execute(Window *window) { KHTMLPart *part = qobject_cast(window->m_frame->m_part); if (!part || !part->jScriptEnabled()) return false; ScriptInterpreter *interpreter = static_cast(part->jScript()->interpreter()); interpreter->setProcessingTimerCallback(true); //kDebug(6070) << "ScheduledAction::execute " << this; if (isFunction) { if (func->implementsCall()) { // #### check this Q_ASSERT( part ); if ( part ) { KJS::Interpreter *interpreter = part->jScript()->interpreter(); ExecState *exec = interpreter->globalExec(); Q_ASSERT( window == interpreter->globalObject() ); JSObject *obj( window ); func->call(exec,obj,args); // note that call() creates its own execution state for the func call if (exec->hadException()) exec->clearException(); // Update our document's rendering following the execution of the timeout callback. part->document().updateRendering(); } } } else { part->executeScript(DOM::Node(), code); } interpreter->setProcessingTimerCallback(false); return true; } void ScheduledAction::mark() { if (func && !func->marked()) func->mark(); } ScheduledAction::~ScheduledAction() { args.reset(); //kDebug(6070) << "ScheduledAction::~ScheduledAction " << this; } ////////////////////// WindowQObject //////////////////////// WindowQObject::WindowQObject(Window *w) : parent(w) { //kDebug(6070) << "WindowQObject::WindowQObject " << this; if ( !parent->m_frame ) kDebug(6070) << "WARNING: null part in " ; else connect( parent->m_frame, SIGNAL( destroyed() ), this, SLOT( parentDestroyed() ) ); pauseLevel = 0; lastTimerId = 0; currentlyDispatching = false; } WindowQObject::~WindowQObject() { //kDebug(6070) << "WindowQObject::~WindowQObject " << this; parentDestroyed(); // reuse same code } void WindowQObject::parentDestroyed() { killTimers(); while (!scheduledActions.isEmpty()) delete scheduledActions.takeFirst(); scheduledActions.clear(); } void WindowQObject::pauseTimers() { ++pauseLevel; if (pauseLevel == 1) pauseStart = DateTimeMS::now(); } void WindowQObject::resumeTimers() { --pauseLevel; if (pauseLevel == 0) { // Adjust all timers by the delay length, making sure there is a minimum // margin from current time, however, so we don't go stampeding off if // there is some unwanted recursion, etc. DateTimeMS curTime = DateTimeMS::now(); DateTimeMS earliestDispatch = curTime.addMSecs(5); int delay = pauseStart.msecsTo(curTime); foreach (ScheduledAction *action, scheduledActions) { action->nextTime = action->nextTime.addMSecs(delay); if (earliestDispatch > action->nextTime) action->nextTime = earliestDispatch; } // Dispatch any timers that may have been ignored if ::timerEvent fell in the middle // of a pause.. timerEvent(0); } } int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot) { int id = ++lastTimerId; if (t < 10) t = 10; DateTimeMS nextTime = DateTimeMS::now().addMSecs(t); ScheduledAction *action = new ScheduledAction(handler.qstring(),nextTime,t,singleShot,id); scheduledActions.append(action); setNextTimer(); return id; } int WindowQObject::installTimeout(JSValue *func, List args, int t, bool singleShot) { JSObject *objFunc = func->getObject(); if (!objFunc) return 0; int id = ++lastTimerId; if (t < 10) t = 10; DateTimeMS nextTime = DateTimeMS::now().addMSecs(t); ScheduledAction *action = new ScheduledAction(objFunc,args,nextTime,t,singleShot,id); scheduledActions.append(action); setNextTimer(); return id; } void WindowQObject::clearTimeout(int timerId) { foreach (ScheduledAction *action, scheduledActions) { if (action->timerId == timerId) { scheduledActions.removeAll(action); if (!action->executing) delete action; return; } } } bool WindowQObject::hasTimers() const { return scheduledActions.count(); } void WindowQObject::mark() { foreach (ScheduledAction *action, scheduledActions) { action->mark(); } } void WindowQObject::timerEvent(QTimerEvent *) { killTimers(); if (scheduledActions.isEmpty()) return; if (pauseLevel) return; currentlyDispatching = true; DateTimeMS current = DateTimeMS::now(); // Work out which actions are to be executed. We take a separate copy of // this list since the main one may be modified during action execution QList toExecute; foreach (ScheduledAction *action, scheduledActions) { if (current >= action->nextTime) toExecute.append(action); } // ### verify that the window can't be closed (and action deleted) during execution foreach (ScheduledAction *action, toExecute) { if (!scheduledActions.count(action)) // removed by clearTimeout() continue; action->executing = true; // prevent deletion in clearTimeout() if (parent->part()) { bool ok = action->execute(parent); if ( !ok ) // e.g. JS disabled scheduledActions.removeAll( action ); } if (action->singleShot) scheduledActions.removeAll(action); action->executing = false; if (!scheduledActions.count(action)) delete action; else action->nextTime = action->nextTime.addMSecs(action->interval); } currentlyDispatching = false; // Work out when next event is to occur setNextTimer(); } DateTimeMS DateTimeMS::addMSecs(int s) const { DateTimeMS c = *this; c.mTime = mTime.addMSecs(s); if (s > 0) { if (c.mTime < mTime) c.mDate = mDate.addDays(1); } else { if (c.mTime > mTime) c.mDate = mDate.addDays(-1); } return c; } bool DateTimeMS::operator >(const DateTimeMS &other) const { if (mDate > other.mDate) return true; if (mDate < other.mDate) return false; return mTime > other.mTime; } bool DateTimeMS::operator >=(const DateTimeMS &other) const { if (mDate > other.mDate) return true; if (mDate < other.mDate) return false; return mTime >= other.mTime; } int DateTimeMS::msecsTo(const DateTimeMS &other) const { int d = mDate.daysTo(other.mDate); int ms = mTime.msecsTo(other.mTime); return d*24*60*60*1000 + ms; } DateTimeMS DateTimeMS::now() { DateTimeMS t; QTime before = QTime::currentTime(); t.mDate = QDate::currentDate(); t.mTime = QTime::currentTime(); if (t.mTime < before) t.mDate = QDate::currentDate(); // prevent race condition in hacky way :) return t; } void WindowQObject::setNextTimer() { if (currentlyDispatching) return; // Will schedule at the end if (scheduledActions.isEmpty()) return; QListIterator it(scheduledActions); DateTimeMS nextTime = it.next()->nextTime; while (it.hasNext()) { const DateTimeMS& currTime = it.next()->nextTime; if (nextTime > currTime) nextTime = currTime; } int nextInterval = DateTimeMS::now().msecsTo(nextTime); if (nextInterval < 0) nextInterval = 0; timerIds.append(startTimer(nextInterval)); } void WindowQObject::killTimers() { for (int i = 0; i < timerIds.size(); ++i) { killTimer(timerIds.at(i)); } timerIds.clear(); } void WindowQObject::timeoutClose() { parent->closeNow(); } const ClassInfo FrameArray::info = { "FrameArray", 0, &FrameArrayTable, 0 }; /* @begin FrameArrayTable 2 length FrameArray::Length DontDelete|ReadOnly location FrameArray::Location DontDelete|ReadOnly @end */ JSValue *FrameArray::getValueProperty(ExecState *exec, int token) { switch (token) { case Length: return jsNumber(part->frames().count()); case Location: // non-standard property, but works in NS and IE if (JSObject *obj = Window::retrieveWindow(part)) return obj->get(exec, "location"); return jsUndefined(); default: assert(0); return jsUndefined(); } } JSValue *FrameArray::indexGetter(ExecState *exec, unsigned index) { KParts::ReadOnlyPart *frame = part->frames().at(index); if (frame) return Window::retrieve(frame); return jsUndefined(); } JSValue *FrameArray::nameGetter(ExecState *exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot) { FrameArray *thisObj = static_cast(slot.slotBase()); KParts::ReadOnlyPart *frame = thisObj->part->findFrame(propertyName.qstring()); if (frame) return Window::retrieve(frame); return jsUndefined(); } JSValue *FrameArray::nameFallBackGetter(ExecState *exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot) { FrameArray *thisObj = static_cast(slot.slotBase()); DOM::DocumentImpl* doc = static_cast(thisObj->part->document().handle()); if (doc) { DOM::HTMLCollectionImpl docuAll(doc, DOM::HTMLCollectionImpl::DOC_ALL); DOM::NodeImpl* node = docuAll.namedItem(propertyName.domString()); if (node) { if (node->id() == ID_FRAME || node->id() == ID_IFRAME) { //Return the Window object. KHTMLPart* part = static_cast(node)->contentPart(); if (part) return Window::retrieveWindow(part); else return jsUndefined(); } else { //Just a regular node.. return getDOMNode(exec, node); } } } else { kWarning(6070) << "Missing own document in FrameArray::get()"; } return jsUndefined(); } bool FrameArray::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { #ifdef KJS_VERBOSE kDebug(6070) << "FrameArray::getOwnPropertySlot " << propertyName.qstring() << " part=" << (void*)part; #endif if (part.isNull()) { slot.setUndefined(this); return true; } if (getStaticOwnValueSlot(&FrameArrayTable, this, propertyName, slot)) return true; // check for the name or number KParts::ReadOnlyPart *frame = part->findFrame(propertyName.qstring()); if (frame) { slot.setCustom(this, nameGetter); return true; } if (getIndexSlot(this, part->frames().count(), propertyName, slot)) return true; // Fun IE quirk: name lookup in there is actually done by document.all // hence, it can find non-frame things (and even let them hide frame ones!) // We don't quite do that, but do this as a fallback. DOM::DocumentImpl* doc = static_cast(part->document().handle()); DOM::HTMLCollectionImpl docuAll(doc, DOM::HTMLCollectionImpl::DOC_ALL); if (docuAll.namedItem(propertyName.domString())) { slot.setCustom(this, nameFallBackGetter); return true; } return JSObject::getOwnPropertySlot(exec, propertyName, slot); } UString FrameArray::toString(ExecState *) const { return "[object FrameArray]"; } JSValue* FrameArray::callAsFunction(ExecState *exec, JSObject * /*thisObj*/, const List &args) { //IE supports a subset of the get functionality as call... //... basically, when the return is a window, it supports that, otherwise it //errors out. We do a cheap-and-easy emulation of that, and just do the same //thing as get does. if (args.size() == 1) return get(exec, Identifier(args[0]->toString(exec))); return jsUndefined(); } ////////////////////// Location Object //////////////////////// const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 }; /* @begin LocationTable 11 hash Location::Hash DontDelete host Location::Host DontDelete hostname Location::Hostname DontDelete href Location::Href DontDelete pathname Location::Pathname DontDelete port Location::Port DontDelete protocol Location::Protocol DontDelete search Location::Search DontDelete [[==]] Location::EqualEqual DontDelete|ReadOnly assign Location::Assign DontDelete|Function 1 toString Location::ToString DontDelete|Function 0 replace Location::Replace DontDelete|Function 1 reload Location::Reload DontDelete|Function 0 @end */ KJS_IMPLEMENT_PROTOFUNC(LocationFunc) Location::Location(khtml::ChildFrame *f) : m_frame(f) { //kDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part; } Location::~Location() { //kDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part; } KParts::ReadOnlyPart *Location::part() const { return m_frame ? static_cast(m_frame->m_part) : 0L; } bool Location::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot& slot) { #ifdef KJS_VERBOSE kDebug(6070) << "Location::getOwnPropertySlot " << p.qstring() << " m_part=" << (void*)m_frame->m_part; #endif if (m_frame.isNull() || m_frame->m_part.isNull()) return jsUndefined(); const HashEntry *entry = Lookup::findEntry(&LocationTable, p); if ( entry ) { // properties that work on all Location objects if (entry->value == Replace) { getSlotFromEntry(entry, this, slot); return true; } // XSS check const Window* window = Window::retrieveWindow( m_frame->m_part ); if ( !window || !window->isSafeScript(exec) ) { slot.setUndefined(this); return true; } // XSS check passed - can now dispatch normally. getSlotFromEntry(entry, this, slot); return true; } return JSObject::getOwnPropertySlot(exec, p, slot); } JSValue* Location::getValueProperty(ExecState *exec, int token) const { KUrl url = m_frame->m_part->url(); switch(token) { case Hash: return jsString( UString(url.ref().isNull() ? QString("") : '#' + url.ref()) ); case Host: { UString str = url.host(); if (url.port() > 0) str = str + QString(":") + QString::number((int)url.port()); return jsString(str); // Note: this is the IE spec. The NS spec swaps the two, it says // "The hostname property is the concatenation of the host and port properties, separated by a colon." // Bleh. } case Hostname: return jsString( UString(url.host()) ); case Href: if (url.isEmpty()) return jsString("about:blank"); else if (!url.hasPath()) return jsString( UString(url.prettyUrl()+'/') ); else return jsString( UString(url.prettyUrl()) ); case Pathname: if (url.isEmpty()) return jsString(""); return jsString( UString(url.path().isEmpty() ? QString("/") : url.path()) ); case Port: return jsString( UString(url.port() ? QString::number((int)url.port()) : QLatin1String("")) ); case Protocol: return jsString( UString(url.protocol()+':') ); case Search: return jsString( UString(url.query()) ); case EqualEqual: // [[==]] return jsString(toString(exec)); } return jsUndefined(); } void Location::put(ExecState *exec, const Identifier &p, JSValue *v, int attr) { #ifdef KJS_VERBOSE kDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_frame->m_part; #endif if (m_frame.isNull() || m_frame->m_part.isNull()) return; const Window* window = Window::retrieveWindow( m_frame->m_part ); if ( !window ) return; KUrl url = m_frame->m_part->url(); const HashEntry *entry = Lookup::findEntry(&LocationTable, p); if (entry) { // XSS check. Only new hrefs can be set from other sites if (entry->value != Href && !window->isSafeScript(exec)) return; QString str = v->toString(exec).qstring(); switch (entry->value) { case Href: { KHTMLPart* p =qobject_cast(Window::retrieveActive(exec)->part()); if ( p ) url = p->htmlDocument().completeURL( str ).string(); else url = str; break; } case Hash: // when the hash is already the same ignore it if (str == url.ref()) return; url.setRef(str); break; case Host: { QString host = str.left(str.indexOf(":")); QString port = str.mid(str.indexOf(":")+1); url.setHost(host); url.setPort(port.toUInt()); break; } case Hostname: url.setHost(str); break; case Pathname: url.setPath(str); break; case Port: url.setPort(str.toUInt()); break; case Protocol: url.setProtocol(str); break; case Search: url.setQuery(str); break; } } else { JSObject::put(exec, p, v, attr); return; } Window::retrieveWindow(m_frame->m_part)->goURL(exec, url.url(), false /* don't lock history*/ ); } JSValue *Location::toPrimitive(ExecState *exec, JSType) const { if (m_frame) { Window* window = Window::retrieveWindow( m_frame->m_part ); if ( window && window->isSafeScript(exec) ) return jsString(toString(exec)); } return jsUndefined(); } UString Location::toString(ExecState *exec) const { if (m_frame) { Window* window = Window::retrieveWindow( m_frame->m_part ); if ( window && window->isSafeScript(exec) ) { KUrl url = m_frame->m_part->url(); if (url.isEmpty()) return "about:blank"; else if (!url.hasPath()) return url.prettyUrl()+'/'; else return url.prettyUrl(); } } return ""; } JSValue *LocationFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { KJS_CHECK_THIS( Location, thisObj ); Location *location = static_cast(thisObj); KParts::ReadOnlyPart *part = location->part(); if (!part) return jsUndefined(); Window* window = Window::retrieveWindow(part); if ( !window->isSafeScript(exec) && id != Location::Replace) return jsUndefined(); switch (id) { case Location::Assign: case Location::Replace: Window::retrieveWindow(part)->goURL(exec, args[0]->toString(exec).qstring(), id == Location::Replace); break; case Location::Reload: { KHTMLPart *khtmlpart = qobject_cast(part); if (khtmlpart) khtmlpart->scheduleRedirection(-1, part->url().url(), true/*lock history*/); else part->openUrl(part->url()); break; } case Location::ToString: return jsString(location->toString(exec)); } return jsUndefined(); } ////////////////////// External Object //////////////////////// const ClassInfo External::info = { "External", 0, 0, 0 }; /* @begin ExternalTable 4 addFavorite External::AddFavorite DontDelete|Function 1 @end */ KJS_IMPLEMENT_PROTOFUNC(ExternalFunc) bool External::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot& propertySlot) { return getStaticFunctionSlot(exec, &ExternalTable, this, p, propertySlot); } JSValue *ExternalFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { KJS_CHECK_THIS( External, thisObj ); External *external = static_cast(thisObj); KHTMLPart *part = external->part; if (!part) return jsUndefined(); KHTMLView *widget = part->view(); switch (id) { case External::AddFavorite: { #ifndef KONQ_EMBEDDED if (!widget->dialogsAllowed()) return jsUndefined(); part->xmlDocImpl()->updateRendering(); if (args.size() != 1 && args.size() != 2) return jsUndefined(); QString url = args[0]->toString(exec).qstring(); QString title; if (args.size() == 2) title = args[1]->toString(exec).qstring(); // AK - don't do anything yet, for the moment i // just wanted the base js handling code in cvs return jsUndefined(); QString question; if ( title.isEmpty() ) question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?", url); else question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?", url, title); emit part->browserExtension()->requestFocus(part); QString caption; if (!part->url().host().isEmpty()) caption = part->url().host() + " - "; caption += i18n("JavaScript Attempted Bookmark Insert"); if (KMessageBox::warningYesNo( widget, question, caption, KGuiItem(i18n("Insert")), KGuiItem(i18n("Disallow"))) == KMessageBox::Yes) { KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager(); KBookmarkDialog dlg(mgr, 0); dlg.addBookmark(title, url); } #else return jsUndefined(); #endif break; } default: return jsUndefined(); } return jsUndefined(); } ////////////////////// History Object //////////////////////// const ClassInfo History::info = { "History", 0, 0, 0 }; /* @begin HistoryTable 4 length History::Length DontDelete|ReadOnly back History::Back DontDelete|Function 0 forward History::Forward DontDelete|Function 0 go History::Go DontDelete|Function 1 @end */ KJS_IMPLEMENT_PROTOFUNC(HistoryFunc) bool History::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot& slot) { return getStaticPropertySlot(exec, &HistoryTable, this, p, slot); } JSValue *History::getValueProperty(ExecState *, int token) const { // if previous or next is implemented, make sure its not a major // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/) switch (token) { case Length: { if ( !part ) return jsNumber( 0 ); KParts::BrowserExtension *ext = part->browserExtension(); if ( !ext ) return jsNumber( 0 ); KParts::BrowserInterface *iface = ext->browserInterface(); if ( !iface ) return jsNumber( 0 ); QVariant length = iface->property( "historyLength" ); if ( length.type() != QVariant::UInt ) return jsNumber( 0 ); return jsNumber( length.toUInt() ); } default: kDebug(6070) << "WARNING: Unhandled token in History::getValueProperty : " << token; return jsUndefined(); } } JSValue *HistoryFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) { KJS_CHECK_THIS( History, thisObj ); History *history = static_cast(thisObj); JSValue *v = args[0]; double n = 0.0; if(v) n = v->toInteger(exec); int steps; switch (id) { case History::Back: steps = -1; break; case History::Forward: steps = 1; break; case History::Go: steps = (int)n; break; default: return jsUndefined(); } // Special case for go(0) from a frame -> reload only the frame // go(i!=0) from a frame navigates into the history of the frame only, // in both IE and NS (but not in Mozilla).... we can't easily do that // in Konqueror... if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter { history->part->openUrl( history->part->url() ); /// ## need args.reload=true? } else { // Delay it. // Testcase: history.back(); alert("hello"); Window* window = Window::retrieveWindow( history->part ); window->delayedGoHistory( steps ); } return jsUndefined(); } } // namespace KJS #include "kjs_window.moc" diff --git a/kjs/object.h b/kjs/object.h index 977680c5ba..d13b496197 100644 --- a/kjs/object.h +++ b/kjs/object.h @@ -1,638 +1,649 @@ // -*- c-basic-offset: 2 -*- /* * This file is part of the KDE libraries * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef KJS_OBJECT_H #define KJS_OBJECT_H #include "global.h" #include "JSType.h" #include "interpreter.h" #include "property_map.h" #include "property_slot.h" #include "scope_chain.h" #include namespace KJS { struct HashTable; struct HashEntry; struct ListImp; class InternalFunctionImp; class PropertyNameArray; // ECMA 262-3 8.6.1 // Property attributes enum Attribute { None = 0, ReadOnly = 1 << 1, // property can be only read, not written DontEnum = 1 << 2, // property doesn't appear in (for .. in ..) DontDelete = 1 << 3, // property can't be deleted Internal = 1 << 4, // an internal property, set to bypass checks Function = 1 << 5, // property is a function - only used by static hashtables GetterSetter = 1 << 6 }; // property is a getter or setter /** * Class Information */ struct ClassInfo { /** * A string denoting the class name. Example: "Window". */ const char* className; /** * Pointer to the class information of the base class. * 0L if there is none. */ const ClassInfo *parentClass; /** * Static hash-table of properties. */ const HashTable *propHashTable; /** * Reserved for future extension. */ void *dummy; }; // This is an internal value object which stores getter and setter functions // for a property. class GetterSetterImp : public JSCell { public: JSType type() const { return GetterSetterType; } GetterSetterImp() : getter(0), setter(0) { } virtual JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const; virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); virtual bool toBoolean(ExecState *exec) const; virtual double toNumber(ExecState *exec) const; virtual UString toString(ExecState *exec) const; virtual JSObject *toObject(ExecState *exec) const; virtual void mark(); JSObject *getGetter() { return getter; } void setGetter(JSObject *g) { getter = g; } JSObject *getSetter() { return setter; } void setSetter(JSObject *s) { setter = s; } private: JSObject *getter; JSObject *setter; }; class KJS_EXPORT JSObject : public JSCell { public: /** * Creates a new JSObject with the specified prototype * * @param proto The prototype */ explicit JSObject(JSValue* proto); /** * Creates a new JSObject with a prototype of jsNull() * (that is, the ECMAScript "null" value, not a null object pointer). */ explicit JSObject(); virtual void mark(); virtual JSType type() const; /** * A pointer to a ClassInfo struct for this class. This provides a basic * facility for run-time type information, and can be used to check an * object's class an inheritance (see inherits()). This should * always return a statically declared pointer, or 0 to indicate that * there is no class information. * * This is primarily useful if you have application-defined classes that you * wish to check against for casting purposes. * * For example, to specify the class info for classes FooImp and BarImp, * where FooImp inherits from BarImp, you would add the following in your * class declarations: * * \code * class BarImp : public JSObject { * virtual const ClassInfo *classInfo() const { return &info; } * static const ClassInfo info; * // ... * }; * * class FooImp : public JSObject { * virtual const ClassInfo *classInfo() const { return &info; } * static const ClassInfo info; * // ... * }; * \endcode * * And in your source file: * * \code * const ClassInfo BarImp::info = {"Bar", 0, 0, 0}; // no parent class * const ClassInfo FooImp::info = {"Foo", &BarImp::info, 0, 0}; * \endcode * * @see inherits() */ virtual const ClassInfo *classInfo() const; /** * Checks whether this object inherits from the class with the specified * classInfo() pointer. This requires that both this class and the other * class return a non-NULL pointer for their classInfo() methods (otherwise * it will return false). * * For example, for two JSObject pointers obj1 and obj2, you can check * if obj1's class inherits from obj2's class using the following: * * if (obj1->inherits(obj2->classInfo())) { * // ... * } * * If you have a handle to a statically declared ClassInfo, such as in the * classInfo() example, you can check for inheritance without needing * an instance of the other class: * * if (obj1->inherits(FooImp::info)) { * // ... * } * * @param cinfo The ClassInfo pointer for the class you want to check * inheritance against. * @return true if this object's class inherits from class with the * ClassInfo pointer specified in cinfo */ bool inherits(const ClassInfo *cinfo) const; // internal properties (ECMA 262-3 8.6.2) /** * Returns the prototype of this object. Note that this is not the same as * the "prototype" property. * * See ECMA 8.6.2 * * @return The object's prototype */ JSValue *prototype() const; void setPrototype(JSValue *proto); /** * Returns the class name of the object * * See ECMA 8.6.2 * * @return The object's class name */ /** * Implementation of the [[Class]] internal property (implemented by all * Objects) * * The default implementation uses classInfo(). * You should either implement classInfo(), or * if you simply need a classname, you can reimplement className() * instead. */ virtual UString className() const; /** * Retrieves the specified property from the object. If neither the object * or any other object in it's prototype chain have the property, this * function will return Undefined. * * See ECMA 8.6.2.1 * * @param exec The current execution state * @param propertyName The name of the property to retrieve * * @return The specified property, or Undefined */ JSValue *get(ExecState *exec, const Identifier &propertyName) const; JSValue *get(ExecState *exec, unsigned propertyName) const; bool getPropertySlot(ExecState *, const Identifier&, PropertySlot&); bool getPropertySlot(ExecState *, unsigned, PropertySlot&); virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState *, unsigned index, PropertySlot&); /** * Sets the specified property. * * See ECMA 8.6.2.2 * * @param exec The current execution state * @param propertyName The name of the property to set * @param propertyValue The value to set */ virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None); virtual void put(ExecState *exec, unsigned propertyName, JSValue *value, int attr = None); /** * Used to check whether or not a particular property is allowed to be set * on an object * * See ECMA 8.6.2.3 * * @param exec The current execution state * @param propertyName The name of the property * @return true if the property can be set, otherwise false */ /** * Implementation of the [[CanPut]] internal property (implemented by all * Objects) */ virtual bool canPut(ExecState *exec, const Identifier &propertyName) const; /** * Checks if a property is enumerable, that is if it doesn't have the DontEnum * flag set * * See ECMA 15.2.4 * @param exec The current execution state * @param propertyName The name of the property * @return true if the property is enumerable, otherwise false */ bool propertyIsEnumerable(ExecState *exec, const Identifier &propertyName) const; /** * Checks to see whether the object (or any object in it's prototype chain) * has a property with the specified name. * * See ECMA 8.6.2.4 * * @param exec The current execution state * @param propertyName The name of the property to check for * @return true if the object has the property, otherwise false */ bool hasProperty(ExecState *exec, const Identifier &propertyName) const; bool hasProperty(ExecState *exec, unsigned propertyName) const; /** * Removes the specified property from the object. * * See ECMA 8.6.2.5 * * @param exec The current execution state * @param propertyName The name of the property to delete * @return true if the property was successfully deleted or did not * exist on the object. false if deleting the specified property is not * allowed. */ virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName); virtual bool deleteProperty(ExecState *exec, unsigned propertyName); /** * Converts the object into a primitive value. The value return may differ * depending on the supplied hint * * See ECMA 8.6.2.6 * * @param exec The current execution state * @param hint The desired primitive type to convert to * @return A primitive value converted from the objetc. Note that the * type of primitive value returned may not be the same as the requested * hint. */ /** * Implementation of the [[DefaultValue]] internal property (implemented by * all Objects) */ virtual JSValue *defaultValue(ExecState *exec, JSType hint) const; /** * Whether or not the object implements the construct() method. If this * returns false you should not call the construct() method on this * object (typically, an assertion will fail to indicate this). * * @return true if this object implements the construct() method, otherwise * false */ virtual bool implementsConstruct() const; /** * Creates a new object based on this object. Typically this means the * following: * 1. A new object is created * 2. The prototype of the new object is set to the value of this object's * "prototype" property * 3. The call() method of this object is called, with the new object * passed as the this value * 4. The new object is returned * * In some cases, Host objects may differ from these semantics, although * this is discouraged. * * If an error occurs during construction, the execution state's exception * will be set. This can be tested for with ExecState::hadException(). * Under some circumstances, the exception object may also be returned. * * Note: This function should not be called if implementsConstruct() returns * false, in which case it will result in an assertion failure. * * @param exec The current execution state * @param args The arguments to be passed to call() once the new object has * been created * @return The newly created & initialized object */ /** * Implementation of the [[Construct]] internal property */ virtual JSObject* construct(ExecState* exec, const List& args); virtual JSObject* construct(ExecState* exec, const List& args, const Identifier& functionName, const UString& sourceURL, int lineNumber); /** * Whether or not the object implements the call() method. If this returns * false you should not call the call() method on this object (typically, * an assertion will fail to indicate this). * * @return true if this object implements the call() method, otherwise * false */ virtual bool implementsCall() const; /** * Calls this object as if it is a function. * * Note: This function should not be called if implementsCall() returns * false, in which case it will result in an assertion failure. * * See ECMA 8.6.2.3 * * @param exec The current execution state * @param thisObj The obj to be used as "this" within function execution. * Note that in most cases this will be different from the C++ "this" * object. For example, if the ECMAScript code "window.location->toString()" * is executed, call() will be invoked on the C++ object which implements * the toString method, with the thisObj being window.location * @param args List of arguments to be passed to the function * @return The return value from the function */ JSValue *call(ExecState *exec, JSObject *thisObj, const List &args); virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args); /** * Whether or not the object implements the hasInstance() method. If this * returns false you should not call the hasInstance() method on this * object (typically, an assertion will fail to indicate this). * * @return true if this object implements the hasInstance() method, * otherwise false */ virtual bool implementsHasInstance() const; /** * Checks whether value delegates behavior to this object. Used by the * instanceof operator. * * @param exec The current execution state * @param value The value to check * @return true if value delegates behavior to this object, otherwise * false */ virtual bool hasInstance(ExecState *exec, JSValue *value); virtual void getPropertyNames(ExecState*, PropertyNameArray&); virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const; virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); virtual bool toBoolean(ExecState *exec) const; virtual double toNumber(ExecState *exec) const; virtual UString toString(ExecState *exec) const; virtual JSObject *toObject(ExecState *exec) const; bool getPropertyAttributes(const Identifier& propertyName, unsigned& attributes) const; // Returns whether the object should be treated as undefined when doing equality comparisons virtual bool masqueradeAsUndefined() const { return false; } // This get function only looks at the property map. // This is used e.g. by lookupOrCreateFunction (to cache a function, we don't want // to look up in the prototype, it might already exist there) JSValue *getDirect(const Identifier& propertyName) const { return _prop.get(propertyName); } JSValue **getDirectLocation(const Identifier& propertyName) { return _prop.getLocation(propertyName); } void putDirect(const Identifier &propertyName, JSValue *value, int attr = 0) { _prop.put(propertyName, value, attr); } void putDirect(const Identifier &propertyName, int value, int attr = 0); void removeDirect(const Identifier &propertyName); // convenience to add a function property under the function's own built-in name void putDirectFunction(InternalFunctionImp*, int attr = 0); void fillGetterPropertySlot(PropertySlot& slot, JSValue **location); + void fillDirectLocationSlot(PropertySlot& slot, JSValue **location); void defineGetter(ExecState *exec, const Identifier& propertyName, JSObject *getterFunc); void defineSetter(ExecState *exec, const Identifier& propertyName, JSObject *setterFunc); /** * Remove all properties from this object. * This doesn't take DontDelete into account, and isn't in the ECMA spec. * It's simply a quick way to remove everything stored in the property map. */ void clearProperties() { _prop.clear(); } void saveProperties(SavedProperties &p) const { _prop.save(p); } void restoreProperties(const SavedProperties &p) { _prop.restore(p); } virtual bool isActivation() const { return false; } // This is used to keep track of whether scope object have local // variables introduced by something other than 'var' bool isLocalInjected() const { return _prop.m_objLocalInjected; } void setLocalInjected() { _prop.m_objLocalInjected = true; } protected: PropertyMap _prop; private: const HashEntry* findPropertyHashEntry( const Identifier& propertyName ) const; JSValue *_proto; #ifdef WIN32 JSObject(const JSObject&); JSObject& operator=(const JSObject&); #endif }; /** * Types of Native Errors available. For custom errors, GeneralError * should be used. */ enum ErrorType { GeneralError = 0, EvalError = 1, RangeError = 2, ReferenceError = 3, SyntaxError = 4, TypeError = 5, URIError = 6}; /** * @short Factory methods for error objects. */ class KJS_EXPORT Error { public: /** * Factory method for error objects. * * @param exec The current execution state * @param errtype Type of error. * @param message Optional error message. * @param lineNumber Optional line number. * @param sourceId Optional source id. * @param sourceURL Optional source URL. */ static JSObject *create(ExecState *, ErrorType, const UString &message, int lineNumber, int sourceId, const UString &sourceURL); static JSObject *create(ExecState *, ErrorType, const char *message); /** * Array of error names corresponding to ErrorType */ static const char * const * const errorNames; }; KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const UString &message, int lineNumber, int sourceId, const UString &sourceURL); KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const UString &message); KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const char *message); KJS_EXPORT JSObject *throwError(ExecState *, ErrorType); inline JSObject::JSObject(JSValue* proto) : _proto(proto) { assert(proto); } inline JSObject::JSObject() :_proto(jsNull()) {} inline JSValue *JSObject::prototype() const { return _proto; } inline void JSObject::setPrototype(JSValue *proto) { assert(proto); _proto = proto; } inline bool JSObject::inherits(const ClassInfo *info) const { for (const ClassInfo *ci = classInfo(); ci; ci = ci->parentClass) if (ci == info) return true; return false; } +inline void JSObject::fillDirectLocationSlot(PropertySlot& slot, + JSValue **location) +{ + if (_prop.hasGetterSetterProperties() && + (*location)->type() == GetterSetterType) + fillGetterPropertySlot(slot, location); + else + slot.setValueSlot(this, location); +} + // this method is here to be after the inline declaration of JSObject::inherits inline bool JSCell::isObject(const ClassInfo *info) const { return isObject() && static_cast(this)->inherits(info); } // this method is here to be after the inline declaration of JSCell::isObject inline bool JSValue::isObject(const ClassInfo *c) const { return !JSImmediate::isImmediate(this) && asCell()->isObject(c); } // It may seem crazy to inline a function this large but it makes a big difference // since this is function very hot in variable lookup inline bool JSObject::getPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { JSObject *object = this; slot.setPotentiallyWriteable(); while (true) { if (object->getOwnPropertySlot(exec, propertyName, slot)) return true; JSValue *proto = object->_proto; if (!proto->isObject()) return false; slot.setReadOnly(); object = static_cast(proto); } } // It may seem crazy to inline a function this large, especially a virtual function, // but it makes a big difference to property lookup that derived classes can inline their // base class call to this. ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { if (JSValue **location = getDirectLocation(propertyName)) { if (_prop.hasGetterSetterProperties() && location[0]->type() == GetterSetterType) fillGetterPropertySlot(slot, location); else slot.setValueSlot(this, location); return true; } // non-standard Netscape extension if (propertyName == exec->propertyNames().underscoreProto) { slot.setValueSlot(this, &_proto, PropertySlot::ForbidDirectWrite); return true; } return false; } // FIXME: Put this function in a separate file named something like scope_chain_mark.h -- can't put it in scope_chain.h since it depends on JSObject. inline void ScopeChain::mark() { for (ScopeChainNode *n = _node; n; n = n->next) { JSObject *o = n->object; if (!o->marked()) o->mark(); } } inline void ScopeChain::release() { // This function is only called by deref(), // Deref ensures these conditions are true. assert(_node && _node->refCount == 0); ScopeChainNode *n = _node; do { ScopeChainNode *next = n->next; delete n; n = next; } while (n && --n->refCount == 0); } inline JSValue* JSObject::toPrimitive(ExecState* exec, JSType preferredType) const { return defaultValue(exec, preferredType); } } // namespace #endif // KJS_OBJECT_H