JavaScriptCore:
[WebKit-https.git] / WebCore / bindings / js / JSDocumentCustom.cpp
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "JSDocument.h"
22
23 #include "DOMWindow.h"
24 #include "ExceptionCode.h"
25 #include "Frame.h"
26 #include "FrameLoader.h"
27 #include "HTMLDocument.h"
28 #include "JSDOMWindowCustom.h"
29 #include "JSHTMLDocument.h"
30 #include "JSLocation.h"
31 #include "JSNodeList.h"
32 #include "Location.h"
33 #include "NodeList.h"
34 #include "ScriptController.h"
35 #include "JSNSResolver.h"
36
37 #if ENABLE(SVG)
38 #include "JSSVGDocument.h"
39 #include "SVGDocument.h"
40 #endif
41
42 using namespace KJS;
43
44 namespace WebCore {
45
46 void JSDocument::mark()
47 {
48     JSEventTargetNode::mark();
49     ScriptInterpreter::markDOMNodesForDocument(static_cast<Document*>(impl()));
50 }
51
52 JSValue* JSDocument::location(ExecState* exec) const
53 {
54     Frame* frame = static_cast<Document*>(impl())->frame();
55     if (!frame)
56         return jsNull();
57
58     return toJS(exec, frame->domWindow()->location());
59 }
60
61 void JSDocument::setLocation(ExecState* exec, JSValue* value)
62 {
63     Frame* frame = static_cast<Document*>(impl())->frame();
64     if (!frame)
65         return;
66
67     String str = value->toString(exec);
68
69     // IE and Mozilla both resolve the URL relative to the source frame,
70     // not the target frame.
71     Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
72     if (activeFrame)
73         str = activeFrame->document()->completeURL(str).string();
74
75     bool userGesture = activeFrame->script()->processingUserGesture();
76     frame->loader()->scheduleLocationChange(str, activeFrame->loader()->outgoingReferrer(), false, userGesture);
77 }
78
79 JSValue* JSDocument::querySelector(ExecState* exec, const ArgList& args)
80 {
81     Document* imp = impl();
82     ExceptionCode ec = 0;
83     const UString& selectors = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0));
84     RefPtr<NSResolver> resolver = args.at(exec, 1)->isUndefinedOrNull() ? 0 : toNSResolver(args.at(exec, 1));
85
86     RefPtr<Element> element = imp->querySelector(selectors, resolver.get(), ec, exec);
87     if (exec->hadException())
88         return jsUndefined();
89     JSValue* result = toJS(exec, element.get());
90     setDOMException(exec, ec);
91     return result;
92 }
93
94 JSValue* JSDocument::querySelectorAll(ExecState* exec, const ArgList& args)
95 {
96     Document* imp = impl();
97     ExceptionCode ec = 0;
98     const UString& selectors = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0));
99     RefPtr<NSResolver> resolver = args.at(exec, 1)->isUndefinedOrNull() ? 0 : toNSResolver(args.at(exec, 1));
100
101     RefPtr<NodeList> nodeList = imp->querySelectorAll(selectors, resolver.get(), ec, exec);
102     if (exec->hadException())
103         return jsUndefined();
104     JSValue* result = toJS(exec, nodeList.get());
105     setDOMException(exec, ec);
106     return result;
107 }
108
109 JSValue* toJS(ExecState* exec, Document* doc)
110 {
111     if (!doc)
112         return jsNull();
113
114     JSDocument* ret = static_cast<JSDocument*>(ScriptInterpreter::getDOMObject(doc));
115     if (ret)
116         return ret;
117
118     if (doc->isHTMLDocument())
119         ret = new (exec) JSHTMLDocument(JSHTMLDocumentPrototype::self(exec), static_cast<HTMLDocument*>(doc));
120 #if ENABLE(SVG)
121     else if (doc->isSVGDocument())
122         ret = new (exec) JSSVGDocument(JSSVGDocumentPrototype::self(exec), static_cast<SVGDocument*>(doc));
123 #endif
124     else
125         ret = new (exec) JSDocument(JSDocumentPrototype::self(exec), doc);
126
127     // Make sure the document is kept around by the window object, and works right with the
128     // back/forward cache.
129     if (!doc->frame()) {
130         size_t nodeCount = 0;
131         for (Node* n = doc; n; n = n->traverseNextNode())
132             nodeCount++;
133         
134         exec->heap()->reportExtraMemoryCost(nodeCount * sizeof(Node));
135     }
136
137     ScriptInterpreter::putDOMObject(doc, ret);
138
139     return ret;
140 }
141
142 } // namespace WebCore