2 * Copyright (C) 2007-2009, 2011, 2016, 2017 Apple Inc. All rights reserved.
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.
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.
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.
21 #include "JSDocument.h"
23 #include "ExceptionCode.h"
25 #include "FrameLoader.h"
26 #include "HTMLDocument.h"
27 #include "JSCanvasRenderingContext2D.h"
28 #include "JSDOMConvert.h"
29 #include "JSDOMWindowCustom.h"
30 #include "JSHTMLDocument.h"
31 #include "JSLocation.h"
32 #include "JSXMLDocument.h"
34 #include "NodeTraversal.h"
35 #include "SVGDocument.h"
36 #include "ScriptController.h"
37 #include "TouchList.h"
38 #include "XMLDocument.h"
39 #include <wtf/GetPtr.h>
42 #include "JSWebGLRenderingContextBase.h"
46 #include "JSWebGPURenderingContext.h"
49 #if ENABLE(TOUCH_EVENTS)
51 #include "JSTouchList.h"
58 static inline JSValue createNewDocumentWrapper(ExecState& state, JSDOMGlobalObject& globalObject, Ref<Document>&& passedDocument)
60 auto& document = passedDocument.get();
62 if (document.isHTMLDocument())
63 wrapper = createWrapper<HTMLDocument>(&globalObject, WTFMove(passedDocument));
64 else if (document.isXMLDocument())
65 wrapper = createWrapper<XMLDocument>(&globalObject, WTFMove(passedDocument));
67 wrapper = createWrapper<Document>(&globalObject, WTFMove(passedDocument));
69 reportMemoryForDocumentIfFrameless(state, document);
74 JSObject* cachedDocumentWrapper(ExecState& state, JSDOMGlobalObject& globalObject, Document& document)
76 if (auto* wrapper = getCachedWrapper(globalObject.world(), document))
79 auto* window = document.domWindow();
83 // Creating a wrapper for domWindow might have created a wrapper for document as well.
84 return getCachedWrapper(toJSDOMWindow(state.vm(), toJS(&state, *window))->world(), document);
87 void reportMemoryForDocumentIfFrameless(ExecState& state, Document& document)
89 // Make sure the document is kept around by the window object, and works right with the back/forward cache.
93 size_t memoryCost = 0;
94 for (Node* node = &document; node; node = NodeTraversal::next(*node))
95 memoryCost += node->approximateMemoryCost();
97 // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
98 // https://bugs.webkit.org/show_bug.cgi?id=142595
99 state.heap()->deprecatedReportExtraMemory(memoryCost);
102 JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<Document>&& document)
104 return createNewDocumentWrapper(*state, *globalObject, WTFMove(document));
107 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Document& document)
109 if (auto* wrapper = cachedDocumentWrapper(*state, *globalObject, document))
111 return toJSNewlyCreated(state, globalObject, Ref<Document>(document));
114 #if ENABLE(TOUCH_EVENTS)
115 JSValue JSDocument::createTouchList(ExecState& state)
118 auto scope = DECLARE_THROW_SCOPE(vm);
120 auto touchList = TouchList::create();
122 for (size_t i = 0; i < state.argumentCount(); ++i) {
123 auto* item = JSTouch::toWrapped(vm, state.uncheckedArgument(i));
125 return JSValue::decode(throwArgumentTypeError(state, scope, i, "touches", "Document", "createTouchList", "Touch"));
127 touchList->append(*item);
129 return toJSNewlyCreated(&state, globalObject(), WTFMove(touchList));
133 JSValue JSDocument::getCSSCanvasContext(JSC::ExecState& state)
136 auto scope = DECLARE_THROW_SCOPE(vm);
138 if (UNLIKELY(state.argumentCount() < 4))
139 return throwException(&state, scope, createNotEnoughArgumentsError(&state));
140 auto contextId = state.uncheckedArgument(0).toWTFString(&state);
141 RETURN_IF_EXCEPTION(scope, JSValue());
142 auto name = state.uncheckedArgument(1).toWTFString(&state);
143 RETURN_IF_EXCEPTION(scope, JSValue());
144 auto width = convert<IDLLong>(state, state.uncheckedArgument(2));
145 RETURN_IF_EXCEPTION(scope, JSValue());
146 auto height = convert<IDLLong>(state, state.uncheckedArgument(3));
147 RETURN_IF_EXCEPTION(scope, JSValue());
149 auto* context = wrapped().getCSSCanvasContext(WTFMove(contextId), WTFMove(name), WTFMove(width), WTFMove(height));
154 if (is<WebGLRenderingContextBase>(*context))
155 return toJS(&state, globalObject(), downcast<WebGLRenderingContextBase>(*context));
158 if (is<WebGPURenderingContext>(*context))
159 return toJS(&state, globalObject(), downcast<WebGPURenderingContext>(*context));
162 return toJS(&state, globalObject(), downcast<CanvasRenderingContext2D>(*context));
165 void JSDocument::visitAdditionalChildren(SlotVisitor& visitor)
167 visitor.addOpaqueRoot(static_cast<ScriptExecutionContext*>(&wrapped()));
170 } // namespace WebCore