2 * Copyright (C) 2007, 2008, 2009, 2011 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 "CustomElementDefinitions.h"
24 #include "ExceptionCode.h"
26 #include "FrameLoader.h"
27 #include "HTMLDocument.h"
28 #include "JSCanvasRenderingContext2D.h"
29 #include "JSDOMWindowCustom.h"
30 #include "JSHTMLDocument.h"
31 #include "JSLocation.h"
32 #include "JSNodeOrString.h"
33 #include "JSSVGDocument.h"
35 #include "NodeTraversal.h"
36 #include "SVGDocument.h"
37 #include "ScriptController.h"
38 #include "TouchList.h"
39 #include "XMLDocument.h"
40 #include <wtf/GetPtr.h>
43 #include "JSWebGLRenderingContextBase.h"
46 #if ENABLE(TOUCH_EVENTS)
48 #include "JSTouchList.h"
55 static inline JSValue createNewDocumentWrapper(ExecState& state, JSDOMGlobalObject& globalObject, Document& document)
58 if (document.isHTMLDocument())
59 wrapper = CREATE_DOM_WRAPPER(&globalObject, HTMLDocument, &document);
60 else if (document.isSVGDocument())
61 wrapper = CREATE_DOM_WRAPPER(&globalObject, SVGDocument, &document);
62 else if (document.isXMLDocument())
63 wrapper = CREATE_DOM_WRAPPER(&globalObject, XMLDocument, &document);
65 wrapper = CREATE_DOM_WRAPPER(&globalObject, Document, &document);
67 // Make sure the document is kept around by the window object, and works right with the
68 // back/forward cache.
69 if (!document.frame()) {
71 for (Node* n = &document; n; n = NodeTraversal::next(*n))
74 // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
75 // https://bugs.webkit.org/show_bug.cgi?id=142595
76 state.heap()->deprecatedReportExtraMemory(nodeCount * sizeof(Node));
82 JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Document* document)
87 JSObject* wrapper = getCachedWrapper(globalObject->world(), document);
91 if (DOMWindow* domWindow = document->domWindow()) {
92 globalObject = toJSDOMWindow(toJS(state, domWindow));
93 // Creating a wrapper for domWindow might have created a wrapper for document as well.
94 wrapper = getCachedWrapper(globalObject->world(), document);
99 return createNewDocumentWrapper(*state, *globalObject, *document);
102 JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Document* document)
104 return document ? createNewDocumentWrapper(*state, *globalObject, *document) : jsNull();
107 JSValue JSDocument::prepend(ExecState& state)
109 ExceptionCode ec = 0;
110 wrapped().prepend(toNodeOrStringVector(state), ec);
111 setDOMException(&state, ec);
113 return jsUndefined();
116 JSValue JSDocument::append(ExecState& state)
118 ExceptionCode ec = 0;
119 wrapped().append(toNodeOrStringVector(state), ec);
120 setDOMException(&state, ec);
122 return jsUndefined();
125 #if ENABLE(TOUCH_EVENTS)
126 JSValue JSDocument::createTouchList(ExecState& state)
128 RefPtr<TouchList> touchList = TouchList::create();
130 for (size_t i = 0; i < state.argumentCount(); i++)
131 touchList->append(JSTouch::toWrapped(state.argument(i)));
133 return toJS(&state, globalObject(), touchList.release());
137 #if ENABLE(CUSTOM_ELEMENTS)
138 JSValue JSDocument::defineElement(ExecState& state)
140 AtomicString tagName(state.argument(0).toString(&state)->toAtomicString(&state));
141 if (UNLIKELY(state.hadException()))
142 return jsUndefined();
144 JSObject* object = state.argument(1).getObject();
145 ConstructData callData;
146 if (!object || object->methodTable()->getConstructData(object, callData) == ConstructTypeNone)
147 return throwTypeError(&state, "The second argument must be a constructor");
149 Document& document = wrapped();
150 if (!document.domWindow()) {
151 throwNotSupportedError(state, "Cannot define a custom element in a docuemnt without a browsing context");
152 return jsUndefined();
155 switch (CustomElementDefinitions::checkName(tagName)) {
156 case CustomElementDefinitions::NameStatus::Valid:
158 case CustomElementDefinitions::NameStatus::ConflictsWithBuiltinNames:
159 return throwSyntaxError(&state, "Custom element name cannot be same as one of the builtin elements");
160 case CustomElementDefinitions::NameStatus::NoHyphen:
161 return throwSyntaxError(&state, "Custom element name must contain a hyphen");
162 case CustomElementDefinitions::NameStatus::ContainsUpperCase:
163 return throwSyntaxError(&state, "Custom element name cannot contain an upper case letter");
166 auto& definitions = document.ensureCustomElementDefinitions();
167 if (definitions.findInterface(tagName)) {
168 throwNotSupportedError(state, "Cannot define multiple custom elements with the same tag name");
169 return jsUndefined();
172 if (definitions.containsConstructor(object)) {
173 throwNotSupportedError(state, "Cannot define multiple custom elements with the same class");
174 return jsUndefined();
177 // FIXME: 10. Let prototype be Get(constructor, "prototype"). Rethrow any exceptions.
178 // FIXME: 11. If Type(prototype) is not Object, throw a TypeError exception.
179 // FIXME: 12. Let attachedCallback be Get(prototype, "attachedCallback"). Rethrow any exceptions.
180 // FIXME: 13. Let detachedCallback be Get(prototype, "detachedCallback"). Rethrow any exceptions.
181 // FIXME: 14. Let attributeChangedCallback be Get(prototype, "attributeChangedCallback"). Rethrow any exceptions.
183 QualifiedName name(nullAtom, tagName, HTMLNames::xhtmlNamespaceURI);
184 definitions.addElementDefinition(JSCustomElementInterface::create(name, object, globalObject()));
185 PrivateName uniquePrivateName;
186 globalObject()->putDirect(globalObject()->vm(), uniquePrivateName, object);
188 // FIXME: 17. Let map be registry's upgrade candidates map.
189 // FIXME: 18. Upgrade a newly-defined element given map and definition.
191 return jsUndefined();
195 } // namespace WebCore