diff options
Diffstat (limited to 'WebCore/bindings')
294 files changed, 17789 insertions, 2970 deletions
diff --git a/WebCore/bindings/js/CachedScriptSourceProvider.h b/WebCore/bindings/js/CachedScriptSourceProvider.h index e943fa5..1cdd8aa 100644 --- a/WebCore/bindings/js/CachedScriptSourceProvider.h +++ b/WebCore/bindings/js/CachedScriptSourceProvider.h @@ -29,11 +29,12 @@ #include "CachedResourceClient.h" #include "CachedResourceHandle.h" #include "CachedScript.h" +#include "ScriptSourceProvider.h" #include <parser/SourceCode.h> namespace WebCore { - class CachedScriptSourceProvider : public JSC::SourceProvider, public CachedResourceClient { + class CachedScriptSourceProvider : public ScriptSourceProvider, public CachedResourceClient { public: static PassRefPtr<CachedScriptSourceProvider> create(CachedScript* cachedScript) { return adoptRef(new CachedScriptSourceProvider(cachedScript)); } @@ -45,10 +46,11 @@ namespace WebCore { JSC::UString getRange(int start, int end) const { return JSC::UString(m_cachedScript->script().characters() + start, end - start); } const UChar* data() const { return m_cachedScript->script().characters(); } int length() const { return m_cachedScript->script().length(); } + const String& source() const { return m_cachedScript->script(); } private: CachedScriptSourceProvider(CachedScript* cachedScript) - : SourceProvider(cachedScript->url()) + : ScriptSourceProvider(cachedScript->url()) , m_cachedScript(cachedScript) { m_cachedScript->addClient(this); diff --git a/WebCore/bindings/js/DOMObjectWithSVGContext.h b/WebCore/bindings/js/DOMObjectWithSVGContext.h new file mode 100644 index 0000000..570548d --- /dev/null +++ b/WebCore/bindings/js/DOMObjectWithSVGContext.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 Google, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DOMObjectWithSVGContext_h +#define DOMObjectWithSVGContext_h + +#if ENABLE(SVG) + +#include "JSDOMBinding.h" +#include "SVGElement.h" + +namespace WebCore { + + // FIXME: This class (and file) should be removed once all SVG bindings + // have moved context() onto the various impl() pointers. + class DOMObjectWithSVGContext : public DOMObject { + public: + SVGElement* context() const { return m_context.get(); } + + protected: + DOMObjectWithSVGContext(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject*, SVGElement* context) + : DOMObject(structure) + , m_context(context) + { + // No space to store the JSDOMGlobalObject w/o hitting the CELL_SIZE limit. + } + + protected: // FIXME: Many custom bindings use m_context directly. Making this protected to temporariliy reduce code churn. + RefPtr<SVGElement> m_context; + }; + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // DOMObjectWithSVGContext_h diff --git a/WebCore/bindings/js/GCController.cpp b/WebCore/bindings/js/GCController.cpp index db295c2..59bcfa3 100644 --- a/WebCore/bindings/js/GCController.cpp +++ b/WebCore/bindings/js/GCController.cpp @@ -44,7 +44,7 @@ namespace WebCore { static void* collect(void*) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSDOMWindow::commonJSGlobalData()->heap.collect(); return 0; } @@ -70,13 +70,13 @@ void GCController::garbageCollectSoon() void GCController::gcTimerFired(Timer<GCController>*) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSDOMWindow::commonJSGlobalData()->heap.collect(); } void GCController::garbageCollectNow() { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSDOMWindow::commonJSGlobalData()->heap.collect(); } diff --git a/WebCore/bindings/js/GCController.h b/WebCore/bindings/js/GCController.h index 452019a..4c25407 100644 --- a/WebCore/bindings/js/GCController.h +++ b/WebCore/bindings/js/GCController.h @@ -31,7 +31,7 @@ namespace WebCore { - class GCController : Noncopyable { + class GCController : public Noncopyable { friend GCController& gcController(); public: diff --git a/WebCore/bindings/js/JSAbstractWorkerCustom.cpp b/WebCore/bindings/js/JSAbstractWorkerCustom.cpp new file mode 100644 index 0000000..003f544 --- /dev/null +++ b/WebCore/bindings/js/JSAbstractWorkerCustom.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009 Apple, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WORKERS) + +#include "JSAbstractWorker.h" + +#include "AbstractWorker.h" +#include "JSDOMGlobalObject.h" +#include "JSEventListener.h" +#include "JSEventTarget.h" + +using namespace JSC; + +namespace WebCore { + +void JSAbstractWorker::markChildren(MarkStack& markStack) +{ + Base::markChildren(markStack); + + markIfNotNull(markStack, m_impl->onerror()); + + typedef AbstractWorker::EventListenersMap EventListenersMap; + typedef AbstractWorker::ListenerVector ListenerVector; + EventListenersMap& eventListeners = m_impl->eventListeners(); + for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) { + for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) + (*vecIter)->markJSFunction(markStack); + } +} + +JSValue JSAbstractWorker::addEventListener(ExecState* exec, const ArgList& args) +{ + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext()); + if (!globalObject) + return jsUndefined(); + RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1)); + if (!listener) + return jsUndefined(); + impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec)); + return jsUndefined(); +} + +JSValue JSAbstractWorker::removeEventListener(ExecState* exec, const ArgList& args) +{ + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext()); + if (!globalObject) + return jsUndefined(); + JSEventListener* listener = globalObject->findJSEventListener(args.at(1)); + if (!listener) + return jsUndefined(); + impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec)); + return jsUndefined(); +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/js/JSAttrCustom.cpp b/WebCore/bindings/js/JSAttrCustom.cpp index 4f3c8ee..abd5ad5 100644 --- a/WebCore/bindings/js/JSAttrCustom.cpp +++ b/WebCore/bindings/js/JSAttrCustom.cpp @@ -47,7 +47,7 @@ void JSAttr::setValue(ExecState* exec, JSValue value) Element* ownerElement = imp->ownerElement(); if (ownerElement && (ownerElement->hasTagName(iframeTag) || ownerElement->hasTagName(frameTag))) { - if (equalIgnoringCase(imp->name(), "src") && protocolIsJavaScript(parseURL(attrValue))) { + if (equalIgnoringCase(imp->name(), "src") && protocolIsJavaScript(deprecatedParseURL(attrValue))) { if (!checkNodeSecurity(exec, static_cast<HTMLFrameElementBase*>(ownerElement)->contentDocument())) return; } diff --git a/WebCore/bindings/js/JSAudioConstructor.cpp b/WebCore/bindings/js/JSAudioConstructor.cpp index 74bcad5..87a3880 100644 --- a/WebCore/bindings/js/JSAudioConstructor.cpp +++ b/WebCore/bindings/js/JSAudioConstructor.cpp @@ -42,35 +42,27 @@ namespace WebCore { const ClassInfo JSAudioConstructor::s_info = { "AudioConstructor", 0, 0, 0 }; JSAudioConstructor::JSAudioConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMObject(JSAudioConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) - , m_globalObject(globalObject) + : DOMConstructorWithDocument(JSAudioConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - ASSERT(globalObject->scriptExecutionContext()); - ASSERT(globalObject->scriptExecutionContext()->isDocument()); - - putDirect(exec->propertyNames().prototype, JSHTMLAudioElementPrototype::self(exec, exec->lexicalGlobalObject()), None); + putDirect(exec->propertyNames().prototype, JSHTMLAudioElementPrototype::self(exec, globalObject), None); putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly|DontDelete|DontEnum); } -Document* JSAudioConstructor::document() const -{ - return static_cast<Document*>(m_globalObject->scriptExecutionContext()); -} - static JSObject* constructAudio(ExecState* exec, JSObject* constructor, const ArgList& args) { + JSAudioConstructor* jsAudio = static_cast<JSAudioConstructor*>(constructor); // FIXME: Why doesn't this need the call toJS on the document like JSImageConstructor? - - Document* document = static_cast<JSAudioConstructor*>(constructor)->document(); + Document* document = jsAudio->document(); if (!document) return throwError(exec, ReferenceError, "Audio constructor associated document is unavailable"); RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(HTMLNames::audioTag, document); + audio->setAutobuffer(true); if (args.size() > 0) { audio->setSrc(args.at(0).toString(exec)); audio->scheduleLoad(); } - return asObject(toJS(exec, audio.release())); + return asObject(toJS(exec, jsAudio->globalObject(), audio.release())); } ConstructType JSAudioConstructor::getConstructData(ConstructData& constructData) @@ -79,13 +71,6 @@ ConstructType JSAudioConstructor::getConstructData(ConstructData& constructData) return ConstructTypeHost; } -void JSAudioConstructor::mark() -{ - DOMObject::mark(); - if (!m_globalObject->marked()) - m_globalObject->mark(); -} - } // namespace WebCore #endif // ENABLE(VIDEO) diff --git a/WebCore/bindings/js/JSAudioConstructor.h b/WebCore/bindings/js/JSAudioConstructor.h index 0a3a7ea..3496897 100644 --- a/WebCore/bindings/js/JSAudioConstructor.h +++ b/WebCore/bindings/js/JSAudioConstructor.h @@ -34,21 +34,15 @@ namespace WebCore { - class JSAudioConstructor : public DOMObject { + class JSAudioConstructor : public DOMConstructorWithDocument { public: JSAudioConstructor(JSC::ExecState*, JSDOMGlobalObject*); - Document* document() const; - static const JSC::ClassInfo s_info; - - virtual void mark(); private: virtual JSC::ConstructType getConstructData(JSC::ConstructData&); virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - - JSDOMGlobalObject* m_globalObject; }; } // namespace WebCore diff --git a/WebCore/bindings/js/JSCDATASectionCustom.cpp b/WebCore/bindings/js/JSCDATASectionCustom.cpp index 44a8957..c2738cc 100644 --- a/WebCore/bindings/js/JSCDATASectionCustom.cpp +++ b/WebCore/bindings/js/JSCDATASectionCustom.cpp @@ -32,12 +32,12 @@ using namespace JSC; namespace WebCore { -JSValue toJSNewlyCreated(ExecState* exec, CDATASection* section) +JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, CDATASection* section) { if (!section) return jsNull(); - - return CREATE_DOM_NODE_WRAPPER(exec, CDATASection, section); + + return CREATE_DOM_NODE_WRAPPER(exec, globalObject, CDATASection, section); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSCSSRuleCustom.cpp b/WebCore/bindings/js/JSCSSRuleCustom.cpp index 2c20431..1b96c06 100644 --- a/WebCore/bindings/js/JSCSSRuleCustom.cpp +++ b/WebCore/bindings/js/JSCSSRuleCustom.cpp @@ -49,46 +49,45 @@ using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, CSSRule* rule) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSRule* rule) { if (!rule) return jsNull(); DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), rule); - if (wrapper) return wrapper; switch (rule->type()) { case CSSRule::STYLE_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSStyleRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSStyleRule, rule); break; case CSSRule::MEDIA_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSMediaRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSMediaRule, rule); break; case CSSRule::FONT_FACE_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSFontFaceRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSFontFaceRule, rule); break; case CSSRule::PAGE_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSPageRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSPageRule, rule); break; case CSSRule::IMPORT_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSImportRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSImportRule, rule); break; case CSSRule::CHARSET_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSCharsetRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSCharsetRule, rule); break; case CSSRule::VARIABLES_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSVariablesRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSVariablesRule, rule); break; case CSSRule::WEBKIT_KEYFRAME_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, WebKitCSSKeyframeRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, WebKitCSSKeyframeRule, rule); break; case CSSRule::WEBKIT_KEYFRAMES_RULE: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, WebKitCSSKeyframesRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, WebKitCSSKeyframesRule, rule); break; default: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSRule, rule); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSRule, rule); } return wrapper; diff --git a/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp b/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp index b07f201..280ec93 100644 --- a/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp +++ b/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp @@ -125,7 +125,7 @@ bool JSCSSStyleDeclaration::canGetItemsForName(ExecState*, CSSStyleDeclaration*, return isCSSPropertyName(propertyName); } -// FIXME: You can get these properties, and set them (see customPut below), +// FIXME: You can get these properties, and set them (see putDelegate below), // but you should also be able to enumerate them. JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { @@ -156,7 +156,7 @@ JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, const Identifier& pro } -bool JSCSSStyleDeclaration::customPut(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&) +bool JSCSSStyleDeclaration::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&) { if (!isCSSPropertyName(propertyName)) return false; diff --git a/WebCore/bindings/js/JSCSSValueCustom.cpp b/WebCore/bindings/js/JSCSSValueCustom.cpp index ad0cee1..87a5760 100644 --- a/WebCore/bindings/js/JSCSSValueCustom.cpp +++ b/WebCore/bindings/js/JSCSSValueCustom.cpp @@ -44,7 +44,7 @@ using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, CSSValue* value) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSValue* value) { if (!value) return jsNull(); @@ -55,19 +55,19 @@ JSValue toJS(ExecState* exec, CSSValue* value) return wrapper; if (value->isWebKitCSSTransformValue()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, WebKitCSSTransformValue, value); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, WebKitCSSTransformValue, value); else if (value->isValueList()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSValueList, value); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSValueList, value); #if ENABLE(SVG) else if (value->isSVGPaint()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, SVGPaint, value); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, SVGPaint, value); else if (value->isSVGColor()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, SVGColor, value); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, SVGColor, value); #endif else if (value->isPrimitiveValue()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSPrimitiveValue, value); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSPrimitiveValue, value); else - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSValue, value); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSValue, value); return wrapper; } diff --git a/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp b/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp index 76db871..398a6799 100644 --- a/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp +++ b/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,11 +28,13 @@ #include "FloatRect.h" #include "HTMLCanvasElement.h" #include "HTMLImageElement.h" +#include "HTMLVideoElement.h" #include "ImageData.h" #include "JSCanvasGradient.h" #include "JSCanvasPattern.h" #include "JSHTMLCanvasElement.h" #include "JSHTMLImageElement.h" +#include "JSHTMLVideoElement.h" #include "JSImageData.h" #include <runtime/Error.h> @@ -230,6 +232,29 @@ JSValue JSCanvasRenderingContext2D::drawImage(ExecState* exec, const ArgList& ar default: return throwError(exec, SyntaxError); } +#if ENABLE(VIDEO) + } else if (o->inherits(&JSHTMLVideoElement::s_info)) { + HTMLVideoElement* video = static_cast<HTMLVideoElement*>(static_cast<JSHTMLElement*>(o)->impl()); + switch (args.size()) { + case 3: + context->drawImage(video, args.at(1).toFloat(exec), args.at(2).toFloat(exec)); + break; + case 5: + context->drawImage(video, args.at(1).toFloat(exec), args.at(2).toFloat(exec), + args.at(3).toFloat(exec), args.at(4).toFloat(exec), ec); + setDOMException(exec, ec); + break; + case 9: + context->drawImage(video, FloatRect(args.at(1).toFloat(exec), args.at(2).toFloat(exec), + args.at(3).toFloat(exec), args.at(4).toFloat(exec)), + FloatRect(args.at(5).toFloat(exec), args.at(6).toFloat(exec), + args.at(7).toFloat(exec), args.at(8).toFloat(exec)), ec); + setDOMException(exec, ec); + break; + default: + return throwError(exec, SyntaxError); + } +#endif } else { setDOMException(exec, TYPE_MISMATCH_ERR); } diff --git a/WebCore/bindings/js/JSCustomPositionCallback.cpp b/WebCore/bindings/js/JSCustomPositionCallback.cpp index 6d892f0..ec2d8e3 100644 --- a/WebCore/bindings/js/JSCustomPositionCallback.cpp +++ b/WebCore/bindings/js/JSCustomPositionCallback.cpp @@ -48,11 +48,12 @@ void JSCustomPositionCallback::handleEvent(Geoposition* geoposition) if (!m_frame->script()->isEnabled()) return; - + + // FIXME: This is likely the wrong globalObject (for prototype chains at least) JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); - JSC::JSLock lock(false); + JSC::JSLock lock(SilenceAssertionsOnly); JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; @@ -67,10 +68,10 @@ void JSCustomPositionCallback::handleEvent(Geoposition* geoposition) } RefPtr<JSCustomPositionCallback> protect(this); - + MarkedArgumentBuffer args; - args.append(toJS(exec, geoposition)); - + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), geoposition)); + globalObject->globalData()->timeoutChecker.start(); call(exec, function, callType, callData, m_callback, args); globalObject->globalData()->timeoutChecker.stop(); diff --git a/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp b/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp index cc6cd55..cda5738 100644 --- a/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp +++ b/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp @@ -48,11 +48,12 @@ void JSCustomPositionErrorCallback::handleEvent(PositionError* positionError) if (!m_frame->script()->isEnabled()) return; - + + // FIXME: This is likely the wrong globalObject (for prototype chains at least) JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); - JSC::JSLock lock(false); + JSC::JSLock lock(SilenceAssertionsOnly); JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; @@ -69,7 +70,7 @@ void JSCustomPositionErrorCallback::handleEvent(PositionError* positionError) RefPtr<JSCustomPositionErrorCallback> protect(this); MarkedArgumentBuffer args; - args.append(toJS(exec, positionError)); + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), positionError)); globalObject->globalData()->timeoutChecker.start(); call(exec, function, callType, callData, m_callback, args); diff --git a/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp index 107a491..d0943de 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp @@ -54,10 +54,11 @@ void JSCustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLR if (!m_frame->script()->isEnabled()) return; + // FIXME: This is likely the wrong globalObject (for prototype chains at least) JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); - JSC::JSLock lock(false); + JSC::JSLock lock(SilenceAssertionsOnly); JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; @@ -74,8 +75,8 @@ void JSCustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLR RefPtr<JSCustomSQLStatementCallback> protect(this); MarkedArgumentBuffer args; - args.append(toJS(exec, transaction)); - args.append(toJS(exec, resultSet)); + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), resultSet)); globalObject->globalData()->timeoutChecker.start(); call(exec, function, callType, callData, m_callback, args); diff --git a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp index 018dabd..6c831ac 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp @@ -54,11 +54,12 @@ bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, if (!m_frame->script()->isEnabled()) return true; - + + // FIXME: This is likely the wrong globalObject (for prototype chains at least) JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); - JSC::JSLock lock(false); + JSC::JSLock lock(SilenceAssertionsOnly); JSValue handleEventFunction = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData handleEventCallData; @@ -77,8 +78,8 @@ bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, RefPtr<JSCustomSQLStatementErrorCallback> protect(this); MarkedArgumentBuffer args; - args.append(toJS(exec, transaction)); - args.append(toJS(exec, error)); + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error)); JSValue result; globalObject->globalData()->timeoutChecker.start(); diff --git a/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp b/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp index a41ac78..3d42f81 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp @@ -94,11 +94,12 @@ void JSCustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bo if (!m_data->frame()->script()->isEnabled()) return; - + + // FIXME: This is likely the wrong globalObject (for prototype chains at least) JSGlobalObject* globalObject = m_data->frame()->script()->globalObject(); ExecState* exec = globalObject->globalExec(); - JSC::JSLock lock(false); + JSC::JSLock lock(SilenceAssertionsOnly); JSValue handleEventFunction = m_data->callback()->get(exec, Identifier(exec, "handleEvent")); CallData handleEventCallData; @@ -117,7 +118,7 @@ void JSCustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bo RefPtr<JSCustomSQLTransactionCallback> protect(this); MarkedArgumentBuffer args; - args.append(toJS(exec, transaction)); + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); globalObject->globalData()->timeoutChecker.start(); if (handleEventCallType != CallTypeNone) diff --git a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp index 324e2bb..2d41bb8 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp @@ -54,10 +54,11 @@ void JSCustomSQLTransactionErrorCallback::handleEvent(SQLError* error) if (!m_frame->script()->isEnabled()) return; + // FIXME: This is likely the wrong globalObject (for prototype chains at least) JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); - JSC::JSLock lock(false); + JSC::JSLock lock(SilenceAssertionsOnly); JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; @@ -74,7 +75,7 @@ void JSCustomSQLTransactionErrorCallback::handleEvent(SQLError* error) RefPtr<JSCustomSQLTransactionErrorCallback> protect(this); MarkedArgumentBuffer args; - args.append(toJS(exec, error)); + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error)); globalObject->globalData()->timeoutChecker.start(); call(exec, function, callType, callData, m_callback, args); diff --git a/WebCore/bindings/js/JSCustomVoidCallback.cpp b/WebCore/bindings/js/JSCustomVoidCallback.cpp index f3f76c4..b4e525b 100644 --- a/WebCore/bindings/js/JSCustomVoidCallback.cpp +++ b/WebCore/bindings/js/JSCustomVoidCallback.cpp @@ -55,7 +55,7 @@ void JSCustomVoidCallback::handleEvent() JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); - JSC::JSLock lock(false); + JSC::JSLock lock(SilenceAssertionsOnly); JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; diff --git a/WebCore/bindings/js/JSCustomXPathNSResolver.cpp b/WebCore/bindings/js/JSCustomXPathNSResolver.cpp index 6361e70..4476be5 100644 --- a/WebCore/bindings/js/JSCustomXPathNSResolver.cpp +++ b/WebCore/bindings/js/JSCustomXPathNSResolver.cpp @@ -72,7 +72,7 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix) if (!m_frame->script()->isEnabled()) return String(); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); @@ -84,7 +84,7 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix) callType = m_customResolver->getCallData(callData); if (callType == CallTypeNone) { // FIXME: Pass actual line number and source URL. - m_frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method.", 0, String()); + m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method.", 0, String()); return String(); } function = m_customResolver; diff --git a/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp b/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp index 7e8d9ce..109308c 100644 --- a/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp +++ b/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp @@ -42,25 +42,25 @@ using namespace JSC; namespace WebCore { -void JSDOMApplicationCache::mark() +void JSDOMApplicationCache::markChildren(MarkStack& markStack) { - DOMObject::mark(); + Base::markChildren(markStack); - markIfNotNull(m_impl->onchecking()); - markIfNotNull(m_impl->onerror()); - markIfNotNull(m_impl->onnoupdate()); - markIfNotNull(m_impl->ondownloading()); - markIfNotNull(m_impl->onprogress()); - markIfNotNull(m_impl->onupdateready()); - markIfNotNull(m_impl->oncached()); - markIfNotNull(m_impl->onobsolete()); + markIfNotNull(markStack, m_impl->onchecking()); + markIfNotNull(markStack, m_impl->onerror()); + markIfNotNull(markStack, m_impl->onnoupdate()); + markIfNotNull(markStack, m_impl->ondownloading()); + markIfNotNull(markStack, m_impl->onprogress()); + markIfNotNull(markStack, m_impl->onupdateready()); + markIfNotNull(markStack, m_impl->oncached()); + markIfNotNull(markStack, m_impl->onobsolete()); typedef DOMApplicationCache::EventListenersMap EventListenersMap; typedef DOMApplicationCache::ListenerVector ListenerVector; EventListenersMap& eventListeners = m_impl->eventListeners(); for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) { for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) - (*vecIter)->markJSFunction(); + (*vecIter)->markJSFunction(markStack); } } diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index 4f58797..566b986 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -18,11 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -// gcc 3.x can't handle including the HashMap pointer specialization in this file -#if defined __GNUC__ && !defined __GLIBCXX__ // less than gcc 3.4 -#define HASH_MAP_PTR_SPEC_WORKAROUND 1 -#endif - #include "config.h" #include "JSDOMBinding.h" @@ -32,6 +27,7 @@ #include "EventException.h" #include "ExceptionCode.h" #include "Frame.h" +#include "HTMLAudioElement.h" #include "HTMLImageElement.h" #include "HTMLScriptElement.h" #include "HTMLNames.h" @@ -288,23 +284,27 @@ static inline bool isObservableThroughDOM(JSNode* jsNode) return true; if (node->hasTagName(scriptTag) && !static_cast<HTMLScriptElement*>(node)->haveFiredLoadEvent()) return true; +#if ENABLE(VIDEO) + if (node->hasTagName(audioTag) && !static_cast<HTMLAudioElement*>(node)->paused()) + return true; +#endif } return false; } -void markDOMNodesForDocument(Document* doc) +void markDOMNodesForDocument(MarkStack& markStack, Document* doc) { JSWrapperCache& nodeDict = doc->wrapperCache(); JSWrapperCache::iterator nodeEnd = nodeDict.end(); for (JSWrapperCache::iterator nodeIt = nodeDict.begin(); nodeIt != nodeEnd; ++nodeIt) { JSNode* jsNode = nodeIt->second; - if (!jsNode->marked() && isObservableThroughDOM(jsNode)) - jsNode->mark(); + if (isObservableThroughDOM(jsNode)) + markStack.append(jsNode); } } -void markActiveObjectsForContext(JSGlobalData& globalData, ScriptExecutionContext* scriptExecutionContext) +void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, ScriptExecutionContext* scriptExecutionContext) { // If an element has pending activity that may result in event listeners being called // (e.g. an XMLHttpRequest), we need to keep JS wrappers alive. @@ -317,19 +317,19 @@ void markActiveObjectsForContext(JSGlobalData& globalData, ScriptExecutionContex // Generally, an active object with pending activity must have a wrapper to mark its listeners. // However, some ActiveDOMObjects don't have JS wrappers (timers created by setTimeout is one example). // FIXME: perhaps need to make sure even timers have a markable 'wrapper'. - if (wrapper && !wrapper->marked()) - wrapper->mark(); + if (wrapper) + markStack.append(wrapper); } } const HashSet<MessagePort*>& messagePorts = scriptExecutionContext->messagePorts(); HashSet<MessagePort*>::const_iterator portsEnd = messagePorts.end(); for (HashSet<MessagePort*>::const_iterator iter = messagePorts.begin(); iter != portsEnd; ++iter) { - if ((*iter)->hasPendingActivity()) { + // If the message port is remotely entangled, then always mark it as in-use because we can't determine reachability across threads. + if (!(*iter)->locallyEntangledPort() || (*iter)->hasPendingActivity()) { DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, *iter); - // A port with pending activity must have a wrapper to mark its listeners, so no null check. - if (!wrapper->marked()) - wrapper->mark(); + if (wrapper) + markStack.append(wrapper); } } } @@ -346,14 +346,14 @@ void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocum addWrapper(wrapper); } -void markDOMObjectWrapper(JSGlobalData& globalData, void* object) +void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* object) { if (!object) return; DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, object); - if (!wrapper || wrapper->marked()) + if (!wrapper) return; - wrapper->mark(); + markStack.append(wrapper); } JSValue jsStringOrNull(ExecState* exec, const String& s) @@ -450,31 +450,36 @@ void setDOMException(ExecState* exec, ExceptionCode ec) if (!ec || exec->hadException()) return; + // FIXME: All callers to setDOMException need to pass in the right global object + // for now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this: + // frames[0].document.createElement(null, null); // throws an exception which should have the subframes prototypes. + JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec); + ExceptionCodeDescription description; getExceptionCodeDescription(ec, description); JSValue errorObject; switch (description.type) { case DOMExceptionType: - errorObject = toJS(exec, DOMCoreException::create(description)); + errorObject = toJS(exec, globalObject, DOMCoreException::create(description)); break; case RangeExceptionType: - errorObject = toJS(exec, RangeException::create(description)); + errorObject = toJS(exec, globalObject, RangeException::create(description)); break; case EventExceptionType: - errorObject = toJS(exec, EventException::create(description)); + errorObject = toJS(exec, globalObject, EventException::create(description)); break; case XMLHttpRequestExceptionType: - errorObject = toJS(exec, XMLHttpRequestException::create(description)); + errorObject = toJS(exec, globalObject, XMLHttpRequestException::create(description)); break; #if ENABLE(SVG) case SVGExceptionType: - errorObject = toJS(exec, SVGException::create(description).get(), 0); + errorObject = toJS(exec, globalObject, SVGException::create(description).get(), 0); break; #endif #if ENABLE(XPATH) case XPathExceptionType: - errorObject = toJS(exec, XPathException::create(description)); + errorObject = toJS(exec, globalObject, XPathException::create(description)); break; #endif } @@ -545,7 +550,7 @@ KURL completeURL(ExecState* exec, const String& relativeURL) JSValue objectToStringFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) { - return new (exec) PrototypeFunction(exec, 0, propertyName, objectProtoFuncToString); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, objectProtoFuncToString); } Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo) diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h index 1378c91..64cfc3a 100644 --- a/WebCore/bindings/js/JSDOMBinding.h +++ b/WebCore/bindings/js/JSDOMBinding.h @@ -1,7 +1,8 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +23,7 @@ #define JSDOMBinding_h #include "JSDOMGlobalObject.h" +#include "Document.h" // For DOMConstructorWithDocument #include <runtime/Completion.h> #include <runtime/Lookup.h> #include <runtime/JSFunction.h> @@ -59,6 +61,72 @@ namespace WebCore { #endif }; + // FIXME: This class should colapse into DOMObject once all DOMObjects are + // updated to store a globalObject pointer. + class DOMObjectWithGlobalPointer : public DOMObject { + public: + JSDOMGlobalObject* globalObject() const { return m_globalObject; } + + ScriptExecutionContext* scriptExecutionContext() const + { + // FIXME: Should never be 0, but can be due to bug 27640. + return m_globalObject->scriptExecutionContext(); + } + + protected: + DOMObjectWithGlobalPointer(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) + : DOMObject(structure) + , m_globalObject(globalObject) + { + // FIXME: This ASSERT is valid, but fires in fast/dom/gc-6.html when trying to create + // new JavaScript objects on detached windows due to DOMWindow::document() + // needing to reach through the frame to get to the Document*. See bug 27640. + // ASSERT(globalObject->scriptExecutionContext()); + } + virtual ~DOMObjectWithGlobalPointer() {} + + void markChildren(JSC::MarkStack& markStack) + { + DOMObject::markChildren(markStack); + markStack.append(m_globalObject); + } + + private: + JSDOMGlobalObject* m_globalObject; + }; + + // Base class for all constructor objects in the JSC bindings. + class DOMConstructorObject : public DOMObjectWithGlobalPointer { + public: + static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + { + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, JSC::HasStandardGetOwnPropertySlot | JSC::ImplementsHasInstance)); + } + + protected: + DOMConstructorObject(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) + : DOMObjectWithGlobalPointer(structure, globalObject) + { + } + }; + + // Constructors using this base class depend on being in a Document and + // can never be used from a WorkerContext. + class DOMConstructorWithDocument : public DOMConstructorObject { + public: + Document* document() const + { + return static_cast<Document*>(scriptExecutionContext()); + } + + protected: + DOMConstructorWithDocument(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(structure, globalObject) + { + ASSERT(globalObject->scriptExecutionContext()->isDocument()); + } + }; + DOMObject* getCachedDOMObjectWrapper(JSC::JSGlobalData&, void* objectHandle); void cacheDOMObjectWrapper(JSC::JSGlobalData&, void* objectHandle, DOMObject* wrapper); void forgetDOMObject(JSC::JSGlobalData&, void* objectHandle); @@ -68,9 +136,9 @@ namespace WebCore { void forgetDOMNode(Document*, Node*); void forgetAllDOMNodesForDocument(Document*); void updateDOMNodeDocument(Node*, Document* oldDocument, Document* newDocument); - void markDOMNodesForDocument(Document*); - void markActiveObjectsForContext(JSC::JSGlobalData&, ScriptExecutionContext*); - void markDOMObjectWrapper(JSC::JSGlobalData& globalData, void* object); + void markDOMNodesForDocument(JSC::MarkStack&, Document*); + void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*); + void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object); JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*); JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, PassRefPtr<JSC::Structure>, const JSC::ClassInfo*); @@ -80,74 +148,86 @@ namespace WebCore { JSC::JSObject* getCachedDOMConstructor(JSC::ExecState*, const JSC::ClassInfo*); void cacheDOMConstructor(JSC::ExecState*, const JSC::ClassInfo*, JSC::JSObject* constructor); + inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec) + { + // FIXME: Callers to this function should be using the global object + // from which the object is being created, instead of assuming the lexical one. + // e.g. subframe.document.body should use the subframe's global object, not the lexical one. + return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); + } + template<class WrapperClass> inline JSC::Structure* getDOMStructure(JSC::ExecState* exec, JSDOMGlobalObject* globalObject) { if (JSC::Structure* structure = getCachedDOMStructure(globalObject, &WrapperClass::s_info)) return structure; return cacheDOMStructure(globalObject, WrapperClass::createStructure(WrapperClass::createPrototype(exec, globalObject)), &WrapperClass::s_info); } - template<class WrapperClass> inline JSC::Structure* getDOMStructure(JSC::ExecState* exec) + template<class WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec) { - return getDOMStructure<WrapperClass>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())); + // FIXME: This function is wrong. It uses the wrong global object for creating the prototype structure. + return getDOMStructure<WrapperClass>(exec, deprecatedGlobalObjectForPrototype(exec)); } template<class WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject) { return static_cast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(exec, static_cast<JSDOMGlobalObject*>(globalObject))->storedPrototype())); } - #define CREATE_DOM_OBJECT_WRAPPER(exec, className, object) createDOMObjectWrapper<JS##className>(exec, static_cast<className*>(object)) - template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, DOMClass* object) + #define CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, className, object) createDOMObjectWrapper<JS##className>(exec, globalObject, static_cast<className*>(object)) + template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object) { ASSERT(object); ASSERT(!getCachedDOMObjectWrapper(exec->globalData(), object)); - WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec), object); + // FIXME: new (exec) could use a different globalData than the globalData this wrapper is cached on. + WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object); cacheDOMObjectWrapper(exec->globalData(), object, wrapper); return wrapper; } - template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, DOMClass* object) + template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object) { if (!object) return JSC::jsNull(); if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), object)) return wrapper; - return createDOMObjectWrapper<WrapperClass>(exec, object); + return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object); } #if ENABLE(SVG) - #define CREATE_SVG_OBJECT_WRAPPER(exec, className, object, context) createDOMObjectWrapper<JS##className>(exec, static_cast<className*>(object), context) - template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, DOMClass* object, SVGElement* context) + #define CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, className, object, context) createDOMObjectWrapper<JS##className>(exec, globalObject, static_cast<className*>(object), context) + template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object, SVGElement* context) { ASSERT(object); ASSERT(!getCachedDOMObjectWrapper(exec->globalData(), object)); - WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec), object, context); + WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object, context); cacheDOMObjectWrapper(exec->globalData(), object, wrapper); return wrapper; } - template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, DOMClass* object, SVGElement* context) + template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object, SVGElement* context) { if (!object) return JSC::jsNull(); if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), object)) return wrapper; - return createDOMObjectWrapper<WrapperClass>(exec, object, context); + return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object, context); } #endif - #define CREATE_DOM_NODE_WRAPPER(exec, className, object) createDOMNodeWrapper<JS##className>(exec, static_cast<className*>(object)) - template<class WrapperClass, class DOMClass> inline JSNode* createDOMNodeWrapper(JSC::ExecState* exec, DOMClass* node) + #define CREATE_DOM_NODE_WRAPPER(exec, globalObject, className, object) createDOMNodeWrapper<JS##className>(exec, globalObject, static_cast<className*>(object)) + template<class WrapperClass, class DOMClass> inline JSNode* createDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node) { ASSERT(node); ASSERT(!getCachedDOMNodeWrapper(node->document(), node)); - WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec), node); + WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, node); + // FIXME: The entire function can be removed, once we fix caching. + // This function is a one-off hack to make Nodes cache in the right global object. cacheDOMNodeWrapper(node->document(), node, wrapper); return wrapper; } - template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMNodeWrapper(JSC::ExecState* exec, DOMClass* node) + template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node) { if (!node) return JSC::jsNull(); if (JSNode* wrapper = getCachedDOMNodeWrapper(node->document(), node)) return wrapper; - return createDOMNodeWrapper<WrapperClass>(exec, node); + return createDOMNodeWrapper<WrapperClass>(exec, globalObject, node); } const JSC::HashTable* getHashTableForGlobalData(JSC::JSGlobalData&, const JSC::HashTable* staticTable); @@ -174,7 +254,28 @@ namespace WebCore { JSC::UString valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null JSC::UString valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined - template <typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, PassRefPtr<T> ptr) { return toJS(exec, ptr.get()); } + // FIXME: These are a stop-gap until all toJS calls can be converted to pass a globalObject + template <typename T> + inline JSC::JSValue toJS(JSC::ExecState* exec, T* ptr) + { + return toJS(exec, deprecatedGlobalObjectForPrototype(exec), ptr); + } + template <typename T> + inline JSC::JSValue toJS(JSC::ExecState* exec, PassRefPtr<T> ptr) + { + return toJS(exec, deprecatedGlobalObjectForPrototype(exec), ptr.get()); + } + template <typename T> + inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* exec, T* ptr) + { + return toJSNewlyCreated(exec, deprecatedGlobalObjectForPrototype(exec), ptr); + } + + template <typename T> + inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<T> ptr) + { + return toJS(exec, globalObject, ptr.get()); + } bool checkNodeSecurity(JSC::ExecState*, Node*); diff --git a/WebCore/bindings/js/JSDOMGlobalObject.cpp b/WebCore/bindings/js/JSDOMGlobalObject.cpp index a7f7b21..68a1db9 100644 --- a/WebCore/bindings/js/JSDOMGlobalObject.cpp +++ b/WebCore/bindings/js/JSDOMGlobalObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -58,19 +58,17 @@ JSDOMGlobalObject::~JSDOMGlobalObject() it->second->clearGlobalObject(); } -void JSDOMGlobalObject::mark() +void JSDOMGlobalObject::markChildren(MarkStack& markStack) { - Base::mark(); + Base::markChildren(markStack); JSDOMStructureMap::iterator end = structures().end(); for (JSDOMStructureMap::iterator it = structures().begin(); it != end; ++it) - it->second->mark(); + it->second->markAggregate(markStack); JSDOMConstructorMap::iterator end2 = constructors().end(); - for (JSDOMConstructorMap::iterator it2 = constructors().begin(); it2 != end2; ++it2) { - if (!it2->second->marked()) - it2->second->mark(); - } + for (JSDOMConstructorMap::iterator it2 = constructors().begin(); it2 != end2; ++it2) + markStack.append(it2->second); } JSEventListener* JSDOMGlobalObject::findJSEventListener(JSValue val) @@ -116,10 +114,15 @@ Event* JSDOMGlobalObject::currentEvent() const return d()->evt; } +JSDOMGlobalObject* toJSDOMGlobalObject(Document* document) +{ + return toJSDOMWindow(document->frame()); +} + JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext) { if (scriptExecutionContext->isDocument()) - return toJSDOMWindow(static_cast<Document*>(scriptExecutionContext)->frame()); + return toJSDOMGlobalObject(static_cast<Document*>(scriptExecutionContext)); #if ENABLE(WORKERS) if (scriptExecutionContext->isWorkerContext()) diff --git a/WebCore/bindings/js/JSDOMGlobalObject.h b/WebCore/bindings/js/JSDOMGlobalObject.h index 8e4e820..855691c 100644 --- a/WebCore/bindings/js/JSDOMGlobalObject.h +++ b/WebCore/bindings/js/JSDOMGlobalObject.h @@ -31,6 +31,7 @@ namespace WebCore { + class Document; class Event; class JSLazyEventListener; class JSEventListener; @@ -67,10 +68,13 @@ namespace WebCore { JSListenersMap& jsEventListeners(); + // Make binding code generation easier. + JSDOMGlobalObject* globalObject() { return this; } + void setCurrentEvent(Event*); Event* currentEvent() const; - virtual void mark(); + virtual void markChildren(JSC::MarkStack&); protected: struct JSDOMGlobalObjectData : public JSC::JSGlobalObject::JSGlobalObjectData { @@ -89,16 +93,6 @@ namespace WebCore { }; template<class ConstructorClass> - inline JSC::JSObject* getDOMConstructor(JSC::ExecState* exec) - { - if (JSC::JSObject* constructor = getCachedDOMConstructor(exec, &ConstructorClass::s_info)) - return constructor; - JSC::JSObject* constructor = new (exec) ConstructorClass(exec); - cacheDOMConstructor(exec, &ConstructorClass::s_info, constructor); - return constructor; - } - - template<class ConstructorClass> inline JSC::JSObject* getDOMConstructor(JSC::ExecState* exec, const JSDOMGlobalObject* globalObject) { if (JSC::JSObject* constructor = globalObject->constructors().get(&ConstructorClass::s_info)) @@ -109,6 +103,7 @@ namespace WebCore { return constructor; } + JSDOMGlobalObject* toJSDOMGlobalObject(Document*); JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext*); } // namespace WebCore diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp index 4fd1139..df6068a 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -26,13 +26,9 @@ #include "CString.h" #include "Console.h" #include "DOMWindow.h" -#include "Element.h" #include "Frame.h" -#include "HTMLCollection.h" -#include "HTMLDocument.h" #include "InspectorController.h" #include "JSDOMWindowCustom.h" -#include "JSHTMLCollection.h" #include "JSNode.h" #include "Logging.h" #include "Page.h" @@ -67,7 +63,7 @@ void JSDOMWindowBase::updateDocument() { ASSERT(d()->impl->document()); ExecState* exec = globalExec(); - symbolTablePutWithAttributes(Identifier(exec, "document"), toJS(exec, d()->impl->document()), DontDelete | ReadOnly); + symbolTablePutWithAttributes(Identifier(exec, "document"), toJS(exec, this, d()->impl->document()), DontDelete | ReadOnly); } ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const @@ -75,88 +71,6 @@ ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const return d()->impl->document(); } -JSValue JSDOMWindowBase::childFrameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) -{ - return toJS(exec, static_cast<JSDOMWindowBase*>(asObject(slot.slotBase()))->impl()->frame()->tree()->child(AtomicString(propertyName))->domWindow()); -} - -JSValue JSDOMWindowBase::indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) -{ - return toJS(exec, static_cast<JSDOMWindowBase*>(asObject(slot.slotBase()))->impl()->frame()->tree()->child(slot.index())->domWindow()); -} - -JSValue JSDOMWindowBase::namedItemGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) -{ - JSDOMWindowBase* thisObj = static_cast<JSDOMWindowBase*>(asObject(slot.slotBase())); - Document* doc = thisObj->impl()->frame()->document(); - ASSERT(thisObj->allowsAccessFrom(exec)); - ASSERT(doc); - ASSERT(doc->isHTMLDocument()); - - RefPtr<HTMLCollection> collection = doc->windowNamedItems(propertyName); - if (collection->length() == 1) - return toJS(exec, collection->firstItem()); - return toJS(exec, collection.get()); -} - -bool JSDOMWindowBase::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) -{ - // Check for child frames by name before built-in properties to - // match Mozilla. This does not match IE, but some sites end up - // naming frames things that conflict with window properties that - // are in Moz but not IE. Since we have some of these, we have to do - // it the Moz way. - if (impl()->frame()->tree()->child(propertyName)) { - slot.setCustom(this, childFrameGetter); - return true; - } - - // Do prototype lookup early so that functions and attributes in the prototype can have - // precedence over the index and name getters. - JSValue proto = prototype(); - if (proto.isObject()) { - if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) { - if (!allowsAccessFrom(exec)) - slot.setUndefined(); - return true; - } - } - - // FIXME: Search the whole frame hierachy somewhere around here. - // We need to test the correct priority order. - - // allow window[1] or parent[1] etc. (#56983) - bool ok; - unsigned i = propertyName.toArrayIndex(&ok); - if (ok && i < impl()->frame()->tree()->childCount()) { - slot.setCustomIndex(this, i, indexGetter); - return true; - } - - if (!allowsAccessFrom(exec)) { - slot.setUndefined(); - return true; - } - - // Allow shortcuts like 'Image1' instead of document.images.Image1 - Document* document = impl()->frame()->document(); - if (document->isHTMLDocument()) { - AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName); - if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) { - slot.setCustom(this, namedItemGetter); - return true; - } - } - - return Base::getOwnPropertySlot(exec, propertyName, slot); -} - -void JSDOMWindowBase::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) -{ - if (allowsAccessFrom(exec)) - Base::put(exec, propertyName, value, slot); -} - String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* other) const { KURL originURL = asJSDOMWindow(other)->impl()->url(); @@ -185,7 +99,7 @@ void JSDOMWindowBase::printErrorMessage(const String& message) const if (settings->privateBrowsingEnabled()) return; - impl()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 1, String()); // FIXME: provide a real line number and source URL. + impl()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String()); // FIXME: provide a real line number and source URL. } ExecState* JSDOMWindowBase::globalExec() @@ -258,6 +172,13 @@ JSGlobalData* JSDOMWindowBase::commonJSGlobalData() return globalData; } +// JSDOMGlobalObject* is ignored, accesing a window in any context will +// use that DOMWindow's prototype chain. +JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) +{ + return toJS(exec, domWindow); +} + JSValue toJS(ExecState*, DOMWindow* domWindow) { if (!domWindow) diff --git a/WebCore/bindings/js/JSDOMWindowBase.h b/WebCore/bindings/js/JSDOMWindowBase.h index 6d93196..84cc81f 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.h +++ b/WebCore/bindings/js/JSDOMWindowBase.h @@ -40,7 +40,6 @@ namespace WebCore { class JSDOMWindowBasePrivate; - // This is the only WebCore JS binding which does not inherit from DOMObject class JSDOMWindowBase : public JSDOMGlobalObject { typedef JSDOMGlobalObject Base; protected: @@ -52,9 +51,6 @@ namespace WebCore { DOMWindow* impl() const { return d()->impl.get(); } virtual ScriptExecutionContext* scriptExecutionContext() const; - virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); - virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); - // Called just before removing this window from the JSDOMWindowShell. void willRemoveFromWindowShell(); @@ -62,15 +58,12 @@ namespace WebCore { static const JSC::ClassInfo s_info; virtual JSC::ExecState* globalExec(); - virtual bool supportsProfiling() const; - virtual bool shouldInterruptScript() const; bool allowsAccessFrom(JSC::ExecState*) const; bool allowsAccessFromNoErrorMessage(JSC::ExecState*) const; bool allowsAccessFrom(JSC::ExecState*, String& message) const; - void printErrorMessage(const String&) const; // Don't call this version of allowsAccessFrom -- it's a slightly incorrect implementation used only by WebScriptObject @@ -89,10 +82,6 @@ namespace WebCore { JSDOMWindowShell* shell; }; - static JSC::JSValue childFrameGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); - static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); - static JSC::JSValue namedItemGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); - bool allowsAccessFromPrivate(const JSC::JSGlobalObject*) const; String crossDomainAccessErrorMessage(const JSC::JSGlobalObject*) const; @@ -100,6 +89,9 @@ namespace WebCore { }; // Returns a JSDOMWindow or jsNull() + // JSDOMGlobalObject* is ignored, accesing a window in any context will + // use that DOMWindow's prototype chain. + JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, DOMWindow*); JSC::JSValue toJS(JSC::ExecState*, DOMWindow*); // Returns JSDOMWindow or 0 diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp index b8c30c7..9798972 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -31,17 +31,21 @@ #include "FrameLoader.h" #include "FrameTree.h" #include "FrameView.h" +#include "HTMLCollection.h" +#include "HTMLDocument.h" #include "History.h" #include "JSAudioConstructor.h" #include "JSDOMWindowShell.h" #include "JSEvent.h" #include "JSEventListener.h" +#include "JSHTMLCollection.h" #include "JSHistory.h" #include "JSImageConstructor.h" #include "JSLocation.h" #include "JSMessageChannelConstructor.h" #include "JSMessagePort.h" #include "JSOptionConstructor.h" +#include "JSSharedWorkerConstructor.h" #include "JSWebKitCSSMatrixConstructor.h" #include "JSWebKitPointConstructor.h" #include "JSWorkerConstructor.h" @@ -58,40 +62,234 @@ #include "Settings.h" #include "WindowFeatures.h" #include <runtime/JSObject.h> +#include <runtime/PrototypeFunction.h> using namespace JSC; namespace WebCore { -void JSDOMWindow::mark() +void JSDOMWindow::markChildren(MarkStack& markStack) { - Base::mark(); + Base::markChildren(markStack); - markEventListeners(impl()->eventListeners()); + markEventListeners(markStack, impl()->eventListeners()); JSGlobalData& globalData = *Heap::heap(this)->globalData(); - markDOMObjectWrapper(globalData, impl()->optionalConsole()); - markDOMObjectWrapper(globalData, impl()->optionalHistory()); - markDOMObjectWrapper(globalData, impl()->optionalLocationbar()); - markDOMObjectWrapper(globalData, impl()->optionalMenubar()); - markDOMObjectWrapper(globalData, impl()->optionalNavigator()); - markDOMObjectWrapper(globalData, impl()->optionalPersonalbar()); - markDOMObjectWrapper(globalData, impl()->optionalScreen()); - markDOMObjectWrapper(globalData, impl()->optionalScrollbars()); - markDOMObjectWrapper(globalData, impl()->optionalSelection()); - markDOMObjectWrapper(globalData, impl()->optionalStatusbar()); - markDOMObjectWrapper(globalData, impl()->optionalToolbar()); - markDOMObjectWrapper(globalData, impl()->optionalLocation()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalConsole()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalHistory()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalLocationbar()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalMenubar()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalPersonalbar()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalScreen()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalScrollbars()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalSelection()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalStatusbar()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalToolbar()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation()); #if ENABLE(DOM_STORAGE) - markDOMObjectWrapper(globalData, impl()->optionalSessionStorage()); - markDOMObjectWrapper(globalData, impl()->optionalLocalStorage()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalSessionStorage()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalLocalStorage()); #endif #if ENABLE(OFFLINE_WEB_APPLICATIONS) - markDOMObjectWrapper(globalData, impl()->optionalApplicationCache()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalApplicationCache()); #endif } +template<NativeFunction nativeFunction, int length> +JSValue nonCachingStaticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +{ + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction); +} + +static JSValue childFrameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +{ + return toJS(exec, static_cast<JSDOMWindow*>(asObject(slot.slotBase()))->impl()->frame()->tree()->child(AtomicString(propertyName))->domWindow()); +} + +static JSValue indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +{ + return toJS(exec, static_cast<JSDOMWindow*>(asObject(slot.slotBase()))->impl()->frame()->tree()->child(slot.index())->domWindow()); +} + +static JSValue namedItemGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +{ + JSDOMWindowBase* thisObj = static_cast<JSDOMWindow*>(asObject(slot.slotBase())); + Document* document = thisObj->impl()->frame()->document(); + + ASSERT(thisObj->allowsAccessFrom(exec)); + ASSERT(document); + ASSERT(document->isHTMLDocument()); + + RefPtr<HTMLCollection> collection = document->windowNamedItems(propertyName); + if (collection->length() == 1) + return toJS(exec, collection->firstItem()); + return toJS(exec, collection.get()); +} + +bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + // When accessing a Window cross-domain, functions are always the native built-in ones, and they + // are not affected by properties changed on the Window or anything in its prototype chain. + // This is consistent with the behavior of Firefox. + + const HashEntry* entry; + + // We don't want any properties other than "close" and "closed" on a closed window. + if (!impl()->frame()) { + // The following code is safe for cross-domain and same domain use. + // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype). + entry = s_info.propHashTable(exec)->entry(exec, propertyName); + if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) { + slot.setCustom(this, entry->propertyGetter()); + return true; + } + entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); + if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) { + slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); + return true; + } + + // FIXME: We should have a message here that explains why the property access/function call was + // not allowed. + slot.setUndefined(); + return true; + } + + // We need to check for cross-domain access here without printing the generic warning message + // because we always allow access to some function, just different ones depending whether access + // is allowed. + String errorMessage; + bool allowsAccess = allowsAccessFrom(exec, errorMessage); + + // Look for overrides before looking at any of our own properties, but ignore overrides completely + // if this is cross-domain access. + if (allowsAccess && JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot)) + return true; + + // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the + // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot. + // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of + // what prototype is actually set on this object. + entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); + if (entry) { + if (entry->attributes() & Function) { + if (entry->function() == jsDOMWindowPrototypeFunctionBlur) { + if (!allowsAccess) { + slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>); + return true; + } + } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) { + if (!allowsAccess) { + slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); + return true; + } + } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) { + if (!allowsAccess) { + slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>); + return true; + } + } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) { + if (!allowsAccess) { + slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>); + return true; + } + } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) { + if (!DOMWindow::canShowModalDialog(impl()->frame())) { + slot.setUndefined(); + return true; + } + } + } + } else { + // Allow access to toString() cross-domain, but always Object.prototype.toString. + if (propertyName == exec->propertyNames().toString) { + if (!allowsAccess) { + slot.setCustom(this, objectToStringFunctionGetter); + return true; + } + } + } + + entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName); + if (entry) { + slot.setCustom(this, entry->propertyGetter()); + return true; + } + + // Check for child frames by name before built-in properties to + // match Mozilla. This does not match IE, but some sites end up + // naming frames things that conflict with window properties that + // are in Moz but not IE. Since we have some of these, we have to do + // it the Moz way. + if (impl()->frame()->tree()->child(propertyName)) { + slot.setCustom(this, childFrameGetter); + return true; + } + + // Do prototype lookup early so that functions and attributes in the prototype can have + // precedence over the index and name getters. + JSValue proto = prototype(); + if (proto.isObject()) { + if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) { + if (!allowsAccess) { + printErrorMessage(errorMessage); + slot.setUndefined(); + } + return true; + } + } + + // FIXME: Search the whole frame hierachy somewhere around here. + // We need to test the correct priority order. + + // allow window[1] or parent[1] etc. (#56983) + bool ok; + unsigned i = propertyName.toArrayIndex(&ok); + if (ok && i < impl()->frame()->tree()->childCount()) { + slot.setCustomIndex(this, i, indexGetter); + return true; + } + + if (!allowsAccess) { + printErrorMessage(errorMessage); + slot.setUndefined(); + return true; + } + + // Allow shortcuts like 'Image1' instead of document.images.Image1 + Document* document = impl()->frame()->document(); + if (document->isHTMLDocument()) { + AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName); + if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) { + slot.setCustom(this, namedItemGetter); + return true; + } + } + + return Base::getOwnPropertySlot(exec, propertyName, slot); +} + +void JSDOMWindow::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +{ + if (!impl()->frame()) + return; + + // Optimization: access JavaScript global variables directly before involving the DOM. + if (JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) { + if (allowsAccessFrom(exec)) + JSGlobalObject::put(exec, propertyName, value, slot); + return; + } + + if (lookupPut<JSDOMWindow>(exec, propertyName, value, s_info.propHashTable(exec), this)) + return; + + if (allowsAccessFrom(exec)) + Base::put(exec, propertyName, value, slot); +} + bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName) { // Only allow deleting properties by frames in the same origin. @@ -100,15 +298,15 @@ bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName return Base::deleteProperty(exec, propertyName); } -bool JSDOMWindow::customGetPropertyNames(ExecState* exec, PropertyNameArray&) +void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) { // Only allow the window to enumerated by frames in the same origin. if (!allowsAccessFrom(exec)) - return true; - return false; + return; + Base::getPropertyNames(exec, propertyNames); } -bool JSDOMWindow::getPropertyAttributes(JSC::ExecState* exec, const Identifier& propertyName, unsigned& attributes) const +bool JSDOMWindow::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const { // Only allow getting property attributes properties by frames in the same origin. if (!allowsAccessFrom(exec)) @@ -161,7 +359,8 @@ JSValue JSDOMWindow::history(ExecState* exec) const if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), history)) return wrapper; - JSHistory* jsHistory = new (exec) JSHistory(getDOMStructure<JSHistory>(exec, const_cast<JSDOMWindow*>(this)), history); + JSDOMWindow* window = const_cast<JSDOMWindow*>(this); + JSHistory* jsHistory = new (exec) JSHistory(getDOMStructure<JSHistory>(exec, window), window, history); cacheDOMObjectWrapper(exec->globalData(), history, jsHistory); return jsHistory; } @@ -172,7 +371,8 @@ JSValue JSDOMWindow::location(ExecState* exec) const if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), location)) return wrapper; - JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, const_cast<JSDOMWindow*>(this)), location); + JSDOMWindow* window = const_cast<JSDOMWindow*>(this); + JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, window), window, location); cacheDOMObjectWrapper(exec->globalData(), location, jsLocation); return jsLocation; } @@ -245,12 +445,12 @@ JSValue JSDOMWindow::audio(ExecState* exec) const JSValue JSDOMWindow::webKitPoint(ExecState* exec) const { - return getDOMConstructor<JSWebKitPointConstructor>(exec); + return getDOMConstructor<JSWebKitPointConstructor>(exec, this); } JSValue JSDOMWindow::webKitCSSMatrix(ExecState* exec) const { - return getDOMConstructor<JSWebKitCSSMatrixConstructor>(exec); + return getDOMConstructor<JSWebKitCSSMatrixConstructor>(exec, this); } JSValue JSDOMWindow::xmlHttpRequest(ExecState* exec) const @@ -261,7 +461,7 @@ JSValue JSDOMWindow::xmlHttpRequest(ExecState* exec) const #if ENABLE(XSLT) JSValue JSDOMWindow::xsltProcessor(ExecState* exec) const { - return getDOMConstructor<JSXSLTProcessorConstructor>(exec); + return getDOMConstructor<JSXSLTProcessorConstructor>(exec, this); } #endif @@ -275,7 +475,14 @@ JSValue JSDOMWindow::messageChannel(ExecState* exec) const #if ENABLE(WORKERS) JSValue JSDOMWindow::worker(ExecState* exec) const { - return getDOMConstructor<JSWorkerConstructor>(exec); + return getDOMConstructor<JSWorkerConstructor>(exec, this); +} +#endif + +#if ENABLE(SHARED_WORKERS) +JSValue JSDOMWindow::sharedWorker(ExecState* exec) const +{ + return getDOMConstructor<JSSharedWorkerConstructor>(exec, this); } #endif diff --git a/WebCore/bindings/js/JSDOMWindowCustom.h b/WebCore/bindings/js/JSDOMWindowCustom.h index 52ef4a0..a0e1b8f 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.h +++ b/WebCore/bindings/js/JSDOMWindowCustom.h @@ -21,7 +21,6 @@ #include "JSDOMWindow.h" #include "JSDOMWindowShell.h" -#include <runtime/PrototypeFunction.h> #include <wtf/AlwaysInline.h> namespace WebCore { @@ -36,121 +35,6 @@ inline const JSDOMWindow* asJSDOMWindow(const JSC::JSGlobalObject* globalObject) return static_cast<const JSDOMWindow*>(globalObject); } -template<JSC::NativeFunction nativeFunction, int length> -JSC::JSValue nonCachingStaticFunctionGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, const JSC::PropertySlot&) -{ - return new (exec) JSC::PrototypeFunction(exec, length, propertyName, nativeFunction); -} - -ALWAYS_INLINE bool JSDOMWindow::customGetOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot) -{ - // When accessing a Window cross-domain, functions are always the native built-in ones, and they - // are not affected by properties changed on the Window or anything in its prototype chain. - // This is consistent with the behavior of Firefox. - - const JSC::HashEntry* entry; - - // We don't want any properties other than "close" and "closed" on a closed window. - if (!impl()->frame()) { - // The following code is safe for cross-domain and same domain use. - // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype). - entry = s_info.propHashTable(exec)->entry(exec, propertyName); - if (entry && !(entry->attributes() & JSC::Function) && entry->propertyGetter() == jsDOMWindowClosed) { - slot.setCustom(this, entry->propertyGetter()); - return true; - } - entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); - if (entry && (entry->attributes() & JSC::Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) { - slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); - return true; - } - - // FIXME: We should have a message here that explains why the property access/function call was - // not allowed. - slot.setUndefined(); - return true; - } - - // We need to check for cross-domain access here without printing the generic warning message - // because we always allow access to some function, just different ones depending whether access - // is allowed. - bool allowsAccess = allowsAccessFromNoErrorMessage(exec); - - // Look for overrides before looking at any of our own properties, but ignore overrides completely - // if this is cross-domain access. - if (allowsAccess && JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot)) - return true; - - // We need this code here because otherwise JSC::Window will stop the search before we even get to the - // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot. - // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of - // what prototype is actually set on this object. - entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); - if (entry) { - if (entry->attributes() & JSC::Function) { - if (entry->function() == jsDOMWindowPrototypeFunctionBlur) { - if (!allowsAccess) { - slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>); - return true; - } - } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) { - if (!allowsAccess) { - slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); - return true; - } - } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) { - if (!allowsAccess) { - slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>); - return true; - } - } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) { - if (!allowsAccess) { - slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>); - return true; - } - } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) { - if (!DOMWindow::canShowModalDialog(impl()->frame())) { - slot.setUndefined(); - return true; - } - } - } - } else { - // Allow access to toString() cross-domain, but always Object.prototype.toString. - if (propertyName == exec->propertyNames().toString) { - if (!allowsAccess) { - slot.setCustom(this, objectToStringFunctionGetter); - return true; - } - } - } - - return false; -} - -inline bool JSDOMWindow::customPut(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot) -{ - if (!impl()->frame()) - return true; - - // Optimization: access JavaScript global variables directly before involving the DOM. - JSC::PropertySlot getSlot; - bool slotIsWriteable; - if (JSGlobalObject::getOwnPropertySlot(exec, propertyName, getSlot, slotIsWriteable)) { - if (allowsAccessFrom(exec)) { - if (slotIsWriteable) { - getSlot.putValue(value); - if (getSlot.isCacheable()) - slot.setExistingProperty(this, getSlot.cachedOffset()); - } else - JSGlobalObject::put(exec, propertyName, value, slot); - } - return true; - } - - return false; -} - inline bool JSDOMWindowBase::allowsAccessFrom(const JSGlobalObject* other) const { if (allowsAccessFromPrivate(other)) diff --git a/WebCore/bindings/js/JSDOMWindowShell.cpp b/WebCore/bindings/js/JSDOMWindowShell.cpp index 1bf478b..efffd42 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -71,11 +71,11 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow) // JSObject methods // ---- -void JSDOMWindowShell::mark() +void JSDOMWindowShell::markChildren(MarkStack& markStack) { - Base::mark(); - if (m_window && !m_window->marked()) - m_window->mark(); + Base::markChildren(markStack); + if (m_window) + markStack.append(m_window); } UString JSDOMWindowShell::className() const diff --git a/WebCore/bindings/js/JSDOMWindowShell.h b/WebCore/bindings/js/JSDOMWindowShell.h index 6f21892..0506283 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.h +++ b/WebCore/bindings/js/JSDOMWindowShell.h @@ -64,7 +64,7 @@ namespace WebCore { } private: - virtual void mark(); + virtual void markChildren(JSC::MarkStack&); virtual JSC::UString className() const; virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); diff --git a/WebCore/bindings/js/JSDataGridColumnListCustom.cpp b/WebCore/bindings/js/JSDataGridColumnListCustom.cpp new file mode 100644 index 0000000..91b3d15 --- /dev/null +++ b/WebCore/bindings/js/JSDataGridColumnListCustom.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(DATAGRID) + +#include "JSDataGridColumnList.h" + +#include "AtomicString.h" +#include "DataGridColumn.h" +#include "DataGridColumnList.h" +#include "JSDataGridColumn.h" + +using namespace JSC; + +namespace WebCore { + +bool JSDataGridColumnList::canGetItemsForName(ExecState*, DataGridColumnList* impl, const Identifier& propertyName) +{ + return impl->itemWithName(propertyName); +} + +JSValue JSDataGridColumnList::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +{ + JSDataGridColumnList* thisObj = static_cast<JSDataGridColumnList*>(asObject(slot.slotBase())); + return toJS(exec, thisObj->globalObject(), thisObj->impl()->itemWithName(propertyName)); +} + +} // namespace WebCore + +#endif diff --git a/WebCore/bindings/js/JSDOMStringListCustom.cpp b/WebCore/bindings/js/JSDataGridDataSource.cpp index ac088af..02b4214 100644 --- a/WebCore/bindings/js/JSDOMStringListCustom.cpp +++ b/WebCore/bindings/js/JSDataGridDataSource.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * Copyright (C) 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,26 +24,32 @@ */ #include "config.h" -#include "JSDOMStringList.h" -#include "DOMStringList.h" +#if ENABLE(DATAGRID) + +#include "JSDataGridDataSource.h" + +#include "Document.h" +#include "Frame.h" +#include "HTMLDataGridElement.h" +#include "JSHTMLDataGridElement.h" +#include "JSDOMWindowBase.h" +#include <runtime/JSLock.h> using namespace JSC; namespace WebCore { -JSValue JSDOMStringList::getByIndex(ExecState* exec, unsigned index) +JSDataGridDataSource::JSDataGridDataSource(JSC::JSValue dataSource, Frame* frame) + : m_dataSource(dataSource) + , m_frame(frame) { - return jsString(exec, impl()->item(index)); } -JSValue JSDOMStringList::item(ExecState* exec, const ArgList& args) +JSDataGridDataSource::~JSDataGridDataSource() { - unsigned index = args.at(0).toUInt32(exec); - if (index >= impl()->length()) - return jsNull(); - - return jsString(exec, impl()->item(index)); } } // namespace WebCore + +#endif // ENABLE(DATAGRID) diff --git a/WebCore/bindings/js/JSDataGridDataSource.h b/WebCore/bindings/js/JSDataGridDataSource.h new file mode 100644 index 0000000..077ef8f --- /dev/null +++ b/WebCore/bindings/js/JSDataGridDataSource.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSDataGridDataSource_h +#define JSDataGridDataSource_h + +#if ENABLE(DATAGRID) + +#include "DataGridDataSource.h" +#include <runtime/JSValue.h> +#include <runtime/Protect.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class Frame; +class HTMLDataGridElement; + +class JSDataGridDataSource : public DataGridDataSource { +public: + static PassRefPtr<JSDataGridDataSource> create(JSC::JSValue dataSource, Frame* frame) + { + return adoptRef(new JSDataGridDataSource(dataSource, frame)); + } + + virtual ~JSDataGridDataSource(); + + virtual bool isJSDataGridDataSource() const { return true; } + JSC::JSValue jsDataSource() const { return m_dataSource.get(); } + +private: + JSDataGridDataSource(JSC::JSValue, Frame*); + + JSC::ProtectedJSValue m_dataSource; + RefPtr<Frame> m_frame; +}; + +inline JSDataGridDataSource* asJSDataGridDataSource(DataGridDataSource* dataSource) +{ + ASSERT(dataSource->isJSDataGridDataSource()); + return static_cast<JSDataGridDataSource*>(dataSource); +} + +inline const JSDataGridDataSource* asJSDataGridDataSource(const DataGridDataSource* dataSource) +{ + ASSERT(dataSource->isJSDataGridDataSource()); + return static_cast<const JSDataGridDataSource*>(dataSource); +} + +} // namespace WebCore + +#endif // ENABLE(DATAGRID) +#endif // JSDataGridDataSource_h diff --git a/WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp b/WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp new file mode 100644 index 0000000..657f9b3 --- /dev/null +++ b/WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009 Apple, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WORKERS) + +#include "JSDedicatedWorkerContext.h" + +using namespace JSC; + +namespace WebCore { + +void JSDedicatedWorkerContext::markChildren(MarkStack& markStack) +{ + Base::markChildren(markStack); + + markIfNotNull(markStack, impl()->onmessage()); +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/js/JSDocumentCustom.cpp b/WebCore/bindings/js/JSDocumentCustom.cpp index 956327a..39a1fc5 100644 --- a/WebCore/bindings/js/JSDocumentCustom.cpp +++ b/WebCore/bindings/js/JSDocumentCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -39,11 +39,11 @@ using namespace JSC; namespace WebCore { -void JSDocument::mark() +void JSDocument::markChildren(MarkStack& markStack) { - JSNode::mark(); - markDOMNodesForDocument(impl()); - markActiveObjectsForContext(*Heap::heap(this)->globalData(), impl()); + JSNode::markChildren(markStack); + markDOMNodesForDocument(markStack, impl()); + markActiveObjectsForContext(markStack, *Heap::heap(this)->globalData(), impl()); } JSValue JSDocument::location(ExecState* exec) const @@ -56,8 +56,7 @@ JSValue JSDocument::location(ExecState* exec) const if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), location)) return wrapper; - JSDOMWindow* window = static_cast<JSDOMWindow*>(exec->lexicalGlobalObject()); - JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, window), location); + JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, globalObject()), globalObject(), location); cacheDOMObjectWrapper(exec->globalData(), location, jsLocation); return jsLocation; } @@ -80,7 +79,7 @@ void JSDocument::setLocation(ExecState* exec, JSValue value) frame->loader()->scheduleLocationChange(str, activeFrame->loader()->outgoingReferrer(), !activeFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture); } -JSValue toJS(ExecState* exec, Document* document) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* document) { if (!document) return jsNull(); @@ -90,13 +89,13 @@ JSValue toJS(ExecState* exec, Document* document) return wrapper; if (document->isHTMLDocument()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, HTMLDocument, document); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLDocument, document); #if ENABLE(SVG) else if (document->isSVGDocument()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, SVGDocument, document); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, SVGDocument, document); #endif else - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, Document, document); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, Document, document); // Make sure the document is kept around by the window object, and works right with the // back/forward cache. diff --git a/WebCore/bindings/js/JSElementCustom.cpp b/WebCore/bindings/js/JSElementCustom.cpp index b12c185..47793d0 100644 --- a/WebCore/bindings/js/JSElementCustom.cpp +++ b/WebCore/bindings/js/JSElementCustom.cpp @@ -53,7 +53,7 @@ using namespace HTMLNames; static inline bool allowSettingSrcToJavascriptURL(ExecState* exec, Element* element, const String& name, const String& value) { - if ((element->hasTagName(iframeTag) || element->hasTagName(frameTag)) && equalIgnoringCase(name, "src") && protocolIsJavaScript(parseURL(value))) { + if ((element->hasTagName(iframeTag) || element->hasTagName(frameTag)) && equalIgnoringCase(name, "src") && protocolIsJavaScript(deprecatedParseURL(value))) { HTMLFrameElementBase* frame = static_cast<HTMLFrameElementBase*>(element); if (!checkNodeSecurity(exec, frame->contentDocument())) return false; @@ -89,7 +89,7 @@ JSValue JSElement::setAttributeNode(ExecState* exec, const ArgList& args) if (!allowSettingSrcToJavascriptURL(exec, imp, newAttr->name(), newAttr->value())) return jsUndefined(); - JSValue result = toJS(exec, WTF::getPtr(imp->setAttributeNode(newAttr, ec))); + JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setAttributeNode(newAttr, ec))); setDOMException(exec, ec); return result; } @@ -123,12 +123,12 @@ JSValue JSElement::setAttributeNodeNS(ExecState* exec, const ArgList& args) if (!allowSettingSrcToJavascriptURL(exec, imp, newAttr->name(), newAttr->value())) return jsUndefined(); - JSValue result = toJS(exec, WTF::getPtr(imp->setAttributeNodeNS(newAttr, ec))); + JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setAttributeNodeNS(newAttr, ec))); setDOMException(exec, ec); return result; } -JSValue toJSNewlyCreated(ExecState* exec, Element* element) +JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Element* element) { if (!element) return jsNull(); @@ -137,15 +137,15 @@ JSValue toJSNewlyCreated(ExecState* exec, Element* element) JSNode* wrapper; if (element->isHTMLElement()) - wrapper = createJSHTMLWrapper(exec, static_cast<HTMLElement*>(element)); + wrapper = createJSHTMLWrapper(exec, globalObject, static_cast<HTMLElement*>(element)); #if ENABLE(SVG) else if (element->isSVGElement()) - wrapper = createJSSVGWrapper(exec, static_cast<SVGElement*>(element)); + wrapper = createJSSVGWrapper(exec, globalObject, static_cast<SVGElement*>(element)); #endif else - wrapper = CREATE_DOM_NODE_WRAPPER(exec, Element, element); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Element, element); return wrapper; } - + } // namespace WebCore diff --git a/WebCore/bindings/js/JSEventCustom.cpp b/WebCore/bindings/js/JSEventCustom.cpp index a020d74..7f9030e 100644 --- a/WebCore/bindings/js/JSEventCustom.cpp +++ b/WebCore/bindings/js/JSEventCustom.cpp @@ -32,6 +32,7 @@ #include "Clipboard.h" #include "Event.h" #include "JSClipboard.h" +#include "JSErrorEvent.h" #include "JSKeyboardEvent.h" #include "JSMessageEvent.h" #include "JSMouseEvent.h" @@ -44,6 +45,7 @@ #include "JSWebKitTransitionEvent.h" #include "JSWheelEvent.h" #include "JSXMLHttpRequestProgressEvent.h" +#include "ErrorEvent.h" #include "KeyboardEvent.h" #include "MessageEvent.h" #include "MouseEvent.h" @@ -79,12 +81,12 @@ namespace WebCore { JSValue JSEvent::clipboardData(ExecState* exec) const { - return impl()->isClipboardEvent() ? toJS(exec, impl()->clipboardData()) : jsUndefined(); + return impl()->isClipboardEvent() ? toJS(exec, globalObject(), impl()->clipboardData()) : jsUndefined(); } -JSValue toJS(ExecState* exec, Event* event) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); if (!event) return jsNull(); @@ -95,45 +97,49 @@ JSValue toJS(ExecState* exec, Event* event) if (event->isUIEvent()) { if (event->isKeyboardEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, KeyboardEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, KeyboardEvent, event); else if (event->isTextEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, TextEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, TextEvent, event); else if (event->isMouseEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, MouseEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, MouseEvent, event); else if (event->isWheelEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, WheelEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, WheelEvent, event); #if ENABLE(SVG) else if (event->isSVGZoomEvent()) - wrapper = CREATE_SVG_OBJECT_WRAPPER(exec, SVGZoomEvent, event, 0); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, SVGZoomEvent, event); #endif #if ENABLE(TOUCH_EVENTS) // Android else if (event->isTouchEvent()) wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, TouchEvent, event); #endif else - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, UIEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, UIEvent, event); } else if (event->isMutationEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, MutationEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, MutationEvent, event); else if (event->isOverflowEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, OverflowEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, OverflowEvent, event); else if (event->isMessageEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, MessageEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, MessageEvent, event); else if (event->isProgressEvent()) { if (event->isXMLHttpRequestProgressEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, XMLHttpRequestProgressEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, XMLHttpRequestProgressEvent, event); else - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, ProgressEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, ProgressEvent, event); } #if ENABLE(DOM_STORAGE) else if (event->isStorageEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, StorageEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, StorageEvent, event); #endif else if (event->isWebKitAnimationEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, WebKitAnimationEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, WebKitAnimationEvent, event); else if (event->isWebKitTransitionEvent()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, WebKitTransitionEvent, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, WebKitTransitionEvent, event); +#if ENABLE(WORKERS) + else if (event->isErrorEvent()) + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, ErrorEvent, event); +#endif else - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, Event, event); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, Event, event); return wrapper; } diff --git a/WebCore/bindings/js/JSEventListener.cpp b/WebCore/bindings/js/JSEventListener.cpp index b9ed685..42e0281 100644 --- a/WebCore/bindings/js/JSEventListener.cpp +++ b/WebCore/bindings/js/JSEventListener.cpp @@ -51,17 +51,17 @@ JSObject* JSEventListener::jsFunction() const return m_jsFunction; } -void JSEventListener::markJSFunction() +void JSEventListener::markJSFunction(MarkStack& markStack) { - if (m_jsFunction && !m_jsFunction->marked()) - m_jsFunction->mark(); - if (m_globalObject && !m_globalObject->marked()) - m_globalObject->mark(); + if (m_jsFunction) + markStack.append(m_jsFunction); + if (m_globalObject) + markStack.append(m_globalObject); } void JSEventListener::handleEvent(Event* event, bool isWindowEvent) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSObject* jsFunction = this->jsFunction(); if (!jsFunction) @@ -71,6 +71,7 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent) // Null check as clearGlobalObject() can clear this and we still get called back by // xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275 // FIXME: Is this check still necessary? Requests are supposed to be stopped before clearGlobalObject() is called. + ASSERT(globalObject); if (!globalObject) return; @@ -107,7 +108,7 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent) ref(); MarkedArgumentBuffer args; - args.append(toJS(exec, event)); + args.append(toJS(exec, globalObject, event)); Event* savedEvent = globalObject->currentEvent(); globalObject->setCurrentEvent(event); @@ -127,7 +128,7 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent) if (isWindowEvent) thisValue = globalObject->toThisObject(exec); else - thisValue = toJS(exec, event->currentTarget()); + thisValue = toJS(exec, globalObject, event->currentTarget()); globalObject->globalData()->timeoutChecker.start(); retval = call(exec, jsFunction, callType, callData, thisValue, args); } @@ -153,6 +154,53 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent) } } +bool JSEventListener::reportError(const String& message, const String& url, int lineNumber) +{ + JSLock lock(SilenceAssertionsOnly); + + JSObject* jsFunction = this->jsFunction(); + if (!jsFunction) + return false; + + JSDOMGlobalObject* globalObject = m_globalObject; + if (!globalObject) + return false; + + ExecState* exec = globalObject->globalExec(); + + CallData callData; + CallType callType = jsFunction->getCallData(callData); + + if (callType == CallTypeNone) + return false; + + MarkedArgumentBuffer args; + args.append(jsString(exec, message)); + args.append(jsString(exec, url)); + args.append(jsNumber(exec, lineNumber)); + + // If this event handler is the first JavaScript to execute, then the + // dynamic global object should be set to the global object of the + // window in which the event occurred. + JSGlobalData* globalData = globalObject->globalData(); + DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject); + + JSValue thisValue = globalObject->toThisObject(exec); + + globalObject->globalData()->timeoutChecker.start(); + JSValue returnValue = call(exec, jsFunction, callType, callData, thisValue, args); + globalObject->globalData()->timeoutChecker.stop(); + + // If an error occurs while handling the script error, it should be bubbled up. + if (exec->hadException()) { + exec->clearException(); + return false; + } + + bool bubbleEvent; + return returnValue.getBoolean(bubbleEvent) && !bubbleEvent; +} + bool JSEventListener::virtualisAttribute() const { return m_isAttribute; diff --git a/WebCore/bindings/js/JSEventListener.h b/WebCore/bindings/js/JSEventListener.h index ce34832..7929169 100644 --- a/WebCore/bindings/js/JSEventListener.h +++ b/WebCore/bindings/js/JSEventListener.h @@ -43,8 +43,9 @@ namespace WebCore { virtual JSC::JSObject* jsFunction() const; private: - virtual void markJSFunction(); + virtual void markJSFunction(JSC::MarkStack&); virtual void handleEvent(Event*, bool isWindowEvent); + virtual bool reportError(const String& message, const String& url, int lineNumber); virtual bool virtualisAttribute() const; void clearJSFunctionInline(); diff --git a/WebCore/bindings/js/JSEventTarget.cpp b/WebCore/bindings/js/JSEventTarget.cpp index 2058098..c34e10e 100644 --- a/WebCore/bindings/js/JSEventTarget.cpp +++ b/WebCore/bindings/js/JSEventTarget.cpp @@ -33,9 +33,13 @@ #include "JSEventListener.h" #include "JSMessagePort.h" #include "JSNode.h" +#include "JSSharedWorker.h" +#include "JSSharedWorkerContext.h" #include "JSXMLHttpRequest.h" #include "JSXMLHttpRequestUpload.h" #include "MessagePort.h" +#include "SharedWorker.h" +#include "SharedWorkerContext.h" #include "XMLHttpRequest.h" #include "XMLHttpRequestUpload.h" @@ -50,17 +54,17 @@ #endif #if ENABLE(WORKERS) +#include "DedicatedWorkerContext.h" +#include "JSDedicatedWorkerContext.h" #include "JSWorker.h" -#include "JSWorkerContext.h" #include "Worker.h" -#include "WorkerContext.h" #endif using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, EventTarget* target) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* target) { if (!target) return jsNull(); @@ -68,36 +72,42 @@ JSValue toJS(ExecState* exec, EventTarget* target) #if ENABLE(SVG) // SVGElementInstance supports both toSVGElementInstance and toNode since so much mouse handling code depends on toNode returning a valid node. if (SVGElementInstance* instance = target->toSVGElementInstance()) - return toJS(exec, instance); + return toJS(exec, globalObject, instance); #endif if (Node* node = target->toNode()) - return toJS(exec, node); + return toJS(exec, globalObject, node); if (DOMWindow* domWindow = target->toDOMWindow()) - return toJS(exec, domWindow); + return toJS(exec, globalObject, domWindow); if (XMLHttpRequest* xhr = target->toXMLHttpRequest()) - // XMLHttpRequest is always created via JS, so we don't need to use cacheDOMObject() here. - return getCachedDOMObjectWrapper(exec->globalData(), xhr); + return toJS(exec, globalObject, xhr); if (XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload()) - return toJS(exec, upload); + return toJS(exec, globalObject, upload); #if ENABLE(OFFLINE_WEB_APPLICATIONS) if (DOMApplicationCache* cache = target->toDOMApplicationCache()) - // DOMApplicationCache is always created via JS, so we don't need to use cacheDOMObject() here. - return getCachedDOMObjectWrapper(exec->globalData(), cache); + return toJS(exec, globalObject, cache); #endif if (MessagePort* messagePort = target->toMessagePort()) - return toJS(exec, messagePort); + return toJS(exec, globalObject, messagePort); #if ENABLE(WORKERS) if (Worker* worker = target->toWorker()) - return toJS(exec, worker); + return toJS(exec, globalObject, worker); - if (WorkerContext* workerContext = target->toWorkerContext()) + if (DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext()) + return toJSDOMGlobalObject(workerContext); +#endif + +#if ENABLE(SHARED_WORKERS) + if (SharedWorker* sharedWorker = target->toSharedWorker()) + return toJS(exec, globalObject, sharedWorker); + + if (SharedWorkerContext* workerContext = target->toSharedWorkerContext()) return toJSDOMGlobalObject(workerContext); #endif @@ -129,7 +139,12 @@ EventTarget* toEventTarget(JSC::JSValue value) #if ENABLE(WORKERS) CONVERT_TO_EVENT_TARGET(Worker) - CONVERT_TO_EVENT_TARGET(WorkerContext) + CONVERT_TO_EVENT_TARGET(DedicatedWorkerContext) +#endif + +#if ENABLE(SHARED_WORKERS) + CONVERT_TO_EVENT_TARGET(SharedWorker) + CONVERT_TO_EVENT_TARGET(SharedWorkerContext) #endif return 0; diff --git a/WebCore/bindings/js/JSEventTarget.h b/WebCore/bindings/js/JSEventTarget.h index 05df056..ddd8232 100644 --- a/WebCore/bindings/js/JSEventTarget.h +++ b/WebCore/bindings/js/JSEventTarget.h @@ -35,8 +35,9 @@ namespace JSC { namespace WebCore { class EventTarget; + class JSDOMGlobalObject; - JSC::JSValue toJS(JSC::ExecState*, EventTarget*); + JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, EventTarget*); EventTarget* toEventTarget(JSC::JSValue); } // namespace WebCore diff --git a/WebCore/bindings/js/JSHTMLAllCollection.h b/WebCore/bindings/js/JSHTMLAllCollection.h index d559d3b..7363e5c 100644 --- a/WebCore/bindings/js/JSHTMLAllCollection.h +++ b/WebCore/bindings/js/JSHTMLAllCollection.h @@ -35,8 +35,8 @@ namespace WebCore { class JSHTMLAllCollection : public JSHTMLCollection { public: - JSHTMLAllCollection(PassRefPtr<JSC::Structure> structure, PassRefPtr<HTMLCollection> collection) - : JSHTMLCollection(structure, collection) + JSHTMLAllCollection(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<HTMLCollection> collection) + : JSHTMLCollection(structure, globalObject, collection) { } diff --git a/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp b/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp index de6565d..37561af 100644 --- a/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp @@ -33,12 +33,12 @@ namespace WebCore { using namespace JSC; -bool JSHTMLAppletElement::customGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +bool JSHTMLAppletElement::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { return runtimeObjectCustomGetOwnPropertySlot(exec, propertyName, slot, this); } -bool JSHTMLAppletElement::customPut(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +bool JSHTMLAppletElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { return runtimeObjectCustomPut(exec, propertyName, value, impl(), slot); } diff --git a/WebCore/bindings/js/JSHTMLCollectionCustom.cpp b/WebCore/bindings/js/JSHTMLCollectionCustom.cpp index 4100468..dd9af74 100644 --- a/WebCore/bindings/js/JSHTMLCollectionCustom.cpp +++ b/WebCore/bindings/js/JSHTMLCollectionCustom.cpp @@ -35,18 +35,18 @@ using namespace JSC; namespace WebCore { -static JSValue getNamedItems(ExecState* exec, HTMLCollection* impl, const Identifier& propertyName) +static JSValue getNamedItems(ExecState* exec, JSHTMLCollection* collection, const Identifier& propertyName) { Vector<RefPtr<Node> > namedItems; - impl->namedItems(propertyName, namedItems); + collection->impl()->namedItems(propertyName, namedItems); if (namedItems.isEmpty()) return jsUndefined(); if (namedItems.size() == 1) - return toJS(exec, namedItems[0].get()); + return toJS(exec, collection->globalObject(), namedItems[0].get()); - return new (exec) JSNamedNodesCollection(exec, namedItems); + return new (exec) JSNamedNodesCollection(exec, collection->globalObject(), namedItems); } // HTMLCollections are strange objects, they support both get and call, @@ -57,7 +57,8 @@ static JSValue JSC_HOST_CALL callHTMLCollection(ExecState* exec, JSObject* funct return jsUndefined(); // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case. - HTMLCollection* collection = static_cast<JSHTMLCollection*>(function)->impl(); + JSHTMLCollection* jsCollection = static_cast<JSHTMLCollection*>(function); + HTMLCollection* collection = jsCollection->impl(); // Also, do we need the TypeError test here ? @@ -67,10 +68,10 @@ static JSValue JSC_HOST_CALL callHTMLCollection(ExecState* exec, JSObject* funct UString string = args.at(0).toString(exec); unsigned index = string.toUInt32(&ok, false); if (ok) - return toJS(exec, collection->item(index)); + return toJS(exec, jsCollection->globalObject(), collection->item(index)); // Support for document.images('<name>') etc. - return getNamedItems(exec, collection, Identifier(exec, string)); + return getNamedItems(exec, jsCollection, Identifier(exec, string)); } // The second arg, if set, is the index of the item we want @@ -82,7 +83,7 @@ static JSValue JSC_HOST_CALL callHTMLCollection(ExecState* exec, JSObject* funct Node* node = collection->namedItem(pstr); while (node) { if (!index) - return toJS(exec, node); + return toJS(exec, jsCollection->globalObject(), node); node = collection->nextNamedItem(pstr); --index; } @@ -97,15 +98,17 @@ CallType JSHTMLCollection::getCallData(CallData& callData) return CallTypeHost; } -bool JSHTMLCollection::canGetItemsForName(ExecState* exec, HTMLCollection* thisObj, const Identifier& propertyName) +bool JSHTMLCollection::canGetItemsForName(ExecState*, HTMLCollection* collection, const Identifier& propertyName) { - return !getNamedItems(exec, thisObj, propertyName).isUndefined(); + Vector<RefPtr<Node> > namedItems; + collection->namedItems(propertyName, namedItems); + return !namedItems.isEmpty(); } JSValue JSHTMLCollection::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { JSHTMLCollection* thisObj = static_cast<JSHTMLCollection*>(asObject(slot.slotBase())); - return getNamedItems(exec, thisObj->impl(), propertyName); + return getNamedItems(exec, thisObj, propertyName); } JSValue JSHTMLCollection::item(ExecState* exec, const ArgList& args) @@ -113,16 +116,16 @@ JSValue JSHTMLCollection::item(ExecState* exec, const ArgList& args) bool ok; uint32_t index = args.at(0).toString(exec).toUInt32(&ok, false); if (ok) - return toJS(exec, impl()->item(index)); - return getNamedItems(exec, impl(), Identifier(exec, args.at(0).toString(exec))); + return toJS(exec, globalObject(), impl()->item(index)); + return getNamedItems(exec, this, Identifier(exec, args.at(0).toString(exec))); } JSValue JSHTMLCollection::namedItem(ExecState* exec, const ArgList& args) { - return getNamedItems(exec, impl(), Identifier(exec, args.at(0).toString(exec))); + return getNamedItems(exec, this, Identifier(exec, args.at(0).toString(exec))); } -JSValue toJS(ExecState* exec, HTMLCollection* collection) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* collection) { if (!collection) return jsNull(); @@ -134,14 +137,14 @@ JSValue toJS(ExecState* exec, HTMLCollection* collection) switch (collection->type()) { case SelectOptions: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, HTMLOptionsCollection, collection); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLOptionsCollection, collection); break; case DocAll: typedef HTMLCollection HTMLAllCollection; - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, HTMLAllCollection, collection); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLAllCollection, collection); break; default: - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, HTMLCollection, collection); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLCollection, collection); break; } diff --git a/WebCore/bindings/js/JSHTMLDataGridElementCustom.cpp b/WebCore/bindings/js/JSHTMLDataGridElementCustom.cpp new file mode 100644 index 0000000..a30f5e4 --- /dev/null +++ b/WebCore/bindings/js/JSHTMLDataGridElementCustom.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(DATAGRID) + +#include "JSHTMLDataGridElement.h" + +#include "Document.h" +#include "HTMLDataGridElement.h" +#include "JSDataGridDataSource.h" + +using namespace JSC; + +namespace WebCore { + +JSValue JSHTMLDataGridElement::dataSource(ExecState*) const +{ + DataGridDataSource* dataSource = static_cast<HTMLDataGridElement*>(impl())->dataSource(); + if (dataSource && dataSource->isJSDataGridDataSource()) + return asJSDataGridDataSource(dataSource)->jsDataSource(); + return jsNull(); +} + +void JSHTMLDataGridElement::setDataSource(ExecState*, JSValue value) +{ + if (value.isNull()) { + static_cast<HTMLDataGridElement*>(impl())->setDataSource(0); + return; + } + + static_cast<HTMLDataGridElement*>(impl())->setDataSource(JSDataGridDataSource::create(value, impl()->document()->frame())); +} + +} // namespace WebCore + +#endif // ENABLE(DATAGRID) diff --git a/WebCore/bindings/js/JSHTMLElementCustom.cpp b/WebCore/bindings/js/JSHTMLElementCustom.cpp index 3345764..4194657 100644 --- a/WebCore/bindings/js/JSHTMLElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLElementCustom.cpp @@ -38,14 +38,14 @@ void JSHTMLElement::pushEventHandlerScope(ExecState* exec, ScopeChain& scope) co HTMLElement* element = impl(); // The document is put on first, fall back to searching it only after the element and form. - scope.push(asObject(toJS(exec, element->ownerDocument()))); + scope.push(asObject(toJS(exec, globalObject(), element->ownerDocument()))); // The form is next, searched before the document, but after the element itself. if (HTMLFormElement* form = element->form()) - scope.push(asObject(toJS(exec, form))); + scope.push(asObject(toJS(exec, globalObject(), form))); // The element is on top, searched first. - scope.push(asObject(toJS(exec, element))); + scope.push(asObject(toJS(exec, globalObject(), element))); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp b/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp index 19aae86..2570bc6 100644 --- a/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp @@ -33,12 +33,12 @@ namespace WebCore { using namespace JSC; -bool JSHTMLEmbedElement::customGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +bool JSHTMLEmbedElement::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { return runtimeObjectCustomGetOwnPropertySlot(exec, propertyName, slot, this); } -bool JSHTMLEmbedElement::customPut(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +bool JSHTMLEmbedElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { return runtimeObjectCustomPut(exec, propertyName, value, impl(), slot); } diff --git a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp index 8bf543c..ffa2d57 100644 --- a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp @@ -45,7 +45,8 @@ bool JSHTMLFormElement::canGetItemsForName(ExecState*, HTMLFormElement* form, co JSValue JSHTMLFormElement::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { - HTMLFormElement* form = static_cast<HTMLFormElement*>(static_cast<JSHTMLElement*>(asObject(slot.slotBase()))->impl()); + JSHTMLElement* jsForm = static_cast<JSHTMLFormElement*>(asObject(slot.slotBase())); + HTMLFormElement* form = static_cast<HTMLFormElement*>(jsForm->impl()); Vector<RefPtr<Node> > namedItems; form->getNamedElements(propertyName, namedItems); @@ -53,7 +54,7 @@ JSValue JSHTMLFormElement::nameGetter(ExecState* exec, const Identifier& propert if (namedItems.size() == 1) return toJS(exec, namedItems[0].get()); if (namedItems.size() > 1) - return new (exec) JSNamedNodesCollection(exec, namedItems); + return new (exec) JSNamedNodesCollection(exec, jsForm->globalObject(), namedItems); return jsUndefined(); } @@ -62,7 +63,7 @@ JSValue JSHTMLFormElement::submit(ExecState* exec, const ArgList&) Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame(); if (!activeFrame) return jsUndefined(); - static_cast<HTMLFormElement*>(impl())->submit(0, false, !activeFrame->script()->anyPageIsProcessingUserGesture(), false); + static_cast<HTMLFormElement*>(impl())->submit(0, false, !activeFrame->script()->anyPageIsProcessingUserGesture()); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp b/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp index 0a5d1f1..c8aea9f 100644 --- a/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp @@ -40,7 +40,7 @@ namespace WebCore { static inline bool allowSettingJavascriptURL(ExecState* exec, HTMLFrameElement* imp, const String& value) { - if (protocolIsJavaScript(parseURL(value))) { + if (protocolIsJavaScript(deprecatedParseURL(value))) { if (!checkNodeSecurity(exec, imp->contentDocument())) return false; } diff --git a/WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp b/WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp index afff977..8e32381 100644 --- a/WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp @@ -44,7 +44,7 @@ void JSHTMLIFrameElement::setSrc(ExecState* exec, JSValue value) String srcValue = valueToStringWithNullCheck(exec, value); - if (protocolIsJavaScript(parseURL(srcValue))) { + if (protocolIsJavaScript(deprecatedParseURL(srcValue))) { if (!checkNodeSecurity(exec, imp->contentDocument())) return; } diff --git a/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp b/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp index f7f12b9..a99e46c 100644 --- a/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp @@ -33,12 +33,12 @@ namespace WebCore { using namespace JSC; -bool JSHTMLObjectElement::customGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +bool JSHTMLObjectElement::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { return runtimeObjectCustomGetOwnPropertySlot(exec, propertyName, slot, this); } -bool JSHTMLObjectElement::customPut(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +bool JSHTMLObjectElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { return runtimeObjectCustomPut(exec, propertyName, value, impl(), slot); } diff --git a/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp b/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp index 460ba08..7bca2db 100644 --- a/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp +++ b/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp @@ -91,7 +91,7 @@ JSValue JSHTMLOptionsCollection::add(ExecState* exec, const ArgList& args) JSValue JSHTMLOptionsCollection::remove(ExecState* exec, const ArgList& args) { HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl()); - JSHTMLSelectElement* base = static_cast<JSHTMLSelectElement*>(asObject(toJS(exec, imp->base()))); + JSHTMLSelectElement* base = static_cast<JSHTMLSelectElement*>(asObject(toJS(exec, globalObject(), imp->base()))); return base->remove(exec, args); } diff --git a/WebCore/bindings/js/JSHistoryCustom.cpp b/WebCore/bindings/js/JSHistoryCustom.cpp index 998a364..a3b15e1 100644 --- a/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/WebCore/bindings/js/JSHistoryCustom.cpp @@ -39,23 +39,23 @@ namespace WebCore { static JSValue nonCachingStaticBackFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) { - return new (exec) PrototypeFunction(exec, 0, propertyName, jsHistoryPrototypeFunctionBack); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionBack); } static JSValue nonCachingStaticForwardFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) { - return new (exec) PrototypeFunction(exec, 0, propertyName, jsHistoryPrototypeFunctionForward); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionForward); } static JSValue nonCachingStaticGoFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) { - return new (exec) PrototypeFunction(exec, 1, propertyName, jsHistoryPrototypeFunctionGo); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsHistoryPrototypeFunctionGo); } -bool JSHistory::customGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +bool JSHistory::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { // When accessing History cross-domain, functions are always the native built-in ones. - // See JSDOMWindow::customGetOwnPropertySlot for additional details. + // See JSDOMWindow::getOwnPropertySlotDelegate for additional details. // Our custom code is only needed to implement the Window cross-domain scheme, so if access is // allowed, return false so the normal lookup will take place. @@ -92,7 +92,7 @@ bool JSHistory::customGetOwnPropertySlot(ExecState* exec, const Identifier& prop return true; } -bool JSHistory::customPut(ExecState* exec, const Identifier&, JSValue, PutPropertySlot&) +bool JSHistory::putDelegate(ExecState* exec, const Identifier&, JSValue, PutPropertySlot&) { // Only allow putting by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) @@ -108,12 +108,12 @@ bool JSHistory::deleteProperty(ExecState* exec, const Identifier& propertyName) return Base::deleteProperty(exec, propertyName); } -bool JSHistory::customGetPropertyNames(ExecState* exec, PropertyNameArray&) +void JSHistory::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) { // Only allow the history object to enumerated by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) - return true; - return false; + return; + Base::getPropertyNames(exec, propertyNames); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSImageConstructor.cpp b/WebCore/bindings/js/JSImageConstructor.cpp index 4a27bb4..faaaf41 100644 --- a/WebCore/bindings/js/JSImageConstructor.cpp +++ b/WebCore/bindings/js/JSImageConstructor.cpp @@ -35,18 +35,9 @@ ASSERT_CLASS_FITS_IN_CELL(JSImageConstructor); const ClassInfo JSImageConstructor::s_info = { "ImageConstructor", 0, 0, 0 }; JSImageConstructor::JSImageConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMObject(JSImageConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) - , m_globalObject(globalObject) + : DOMConstructorWithDocument(JSImageConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - ASSERT(globalObject->scriptExecutionContext()); - ASSERT(globalObject->scriptExecutionContext()->isDocument()); - - putDirect(exec->propertyNames().prototype, JSHTMLImageElementPrototype::self(exec, exec->lexicalGlobalObject()), None); -} - -Document* JSImageConstructor::document() const -{ - return static_cast<Document*>(m_globalObject->scriptExecutionContext()); + putDirect(exec->propertyNames().prototype, JSHTMLImageElementPrototype::self(exec, globalObject), None); } static JSObject* constructImage(ExecState* exec, JSObject* constructor, const ArgList& args) @@ -64,21 +55,22 @@ static JSObject* constructImage(ExecState* exec, JSObject* constructor, const Ar height = args.at(1).toInt32(exec); } - Document* document = static_cast<JSImageConstructor*>(constructor)->document(); + JSImageConstructor* jsConstructor = static_cast<JSImageConstructor*>(constructor); + Document* document = jsConstructor->document(); if (!document) return throwError(exec, ReferenceError, "Image constructor associated document is unavailable"); // Calling toJS on the document causes the JS document wrapper to be // added to the window object. This is done to ensure that JSDocument::mark // will be called (which will cause the image element to be marked if necessary). - toJS(exec, document); + toJS(exec, jsConstructor->globalObject(), document); RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, document); if (widthSet) image->setWidth(width); if (heightSet) image->setHeight(height); - return asObject(toJS(exec, image.release())); + return asObject(toJS(exec, jsConstructor->globalObject(), image.release())); } ConstructType JSImageConstructor::getConstructData(ConstructData& constructData) @@ -87,11 +79,4 @@ ConstructType JSImageConstructor::getConstructData(ConstructData& constructData) return ConstructTypeHost; } -void JSImageConstructor::mark() -{ - DOMObject::mark(); - if (!m_globalObject->marked()) - m_globalObject->mark(); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSImageConstructor.h b/WebCore/bindings/js/JSImageConstructor.h index 8dc7add..0525f5e 100644 --- a/WebCore/bindings/js/JSImageConstructor.h +++ b/WebCore/bindings/js/JSImageConstructor.h @@ -25,19 +25,14 @@ namespace WebCore { - class JSImageConstructor : public DOMObject { + class JSImageConstructor : public DOMConstructorWithDocument { public: JSImageConstructor(JSC::ExecState*, JSDOMGlobalObject*); - Document* document() const; static const JSC::ClassInfo s_info; - - virtual void mark(); private: virtual JSC::ConstructType getConstructData(JSC::ConstructData&); virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - - JSDOMGlobalObject* m_globalObject; }; } // namespace WebCore diff --git a/WebCore/bindings/js/JSImageDataCustom.cpp b/WebCore/bindings/js/JSImageDataCustom.cpp index 32fe58b..fa3b1d5 100644 --- a/WebCore/bindings/js/JSImageDataCustom.cpp +++ b/WebCore/bindings/js/JSImageDataCustom.cpp @@ -36,7 +36,7 @@ using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, ImageData* imageData) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, ImageData* imageData) { if (!imageData) return jsNull(); @@ -45,7 +45,7 @@ JSValue toJS(ExecState* exec, ImageData* imageData) if (wrapper) return wrapper; - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, ImageData, imageData); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, ImageData, imageData); Identifier dataName(exec, "data"); DEFINE_STATIC_LOCAL(RefPtr<Structure>, cpaStructure, (JSByteArray::createStructure(jsNull()))); static const ClassInfo cpaClassInfo = { "CanvasPixelArray", 0, 0, 0 }; diff --git a/WebCore/bindings/js/JSInspectorControllerCustom.cpp b/WebCore/bindings/js/JSInspectorBackendCustom.cpp index b06c9e9..b2eb2d1 100644 --- a/WebCore/bindings/js/JSInspectorControllerCustom.cpp +++ b/WebCore/bindings/js/JSInspectorBackendCustom.cpp @@ -31,7 +31,7 @@ */ #include "config.h" -#include "JSInspectorController.h" +#include "JSInspectorBackend.h" #include "Console.h" #if ENABLE(DATABASE) @@ -41,6 +41,7 @@ #include "ExceptionCode.h" #include "Frame.h" #include "FrameLoader.h" +#include "InspectorBackend.h" #include "InspectorController.h" #include "InspectorResource.h" #include "JSDOMWindow.h" @@ -69,7 +70,7 @@ using namespace JSC; namespace WebCore { -JSValue JSInspectorController::highlightDOMNode(JSC::ExecState*, const JSC::ArgList& args) +JSValue JSInspectorBackend::highlightDOMNode(JSC::ExecState*, const JSC::ArgList& args) { if (args.size() < 1) return jsUndefined(); @@ -87,34 +88,7 @@ JSValue JSInspectorController::highlightDOMNode(JSC::ExecState*, const JSC::ArgL return jsUndefined(); } -JSValue JSInspectorController::getResourceDocumentNode(ExecState* exec, const ArgList& args) -{ - if (args.size() < 1) - return jsUndefined(); - - bool ok = false; - unsigned identifier = args.at(0).toUInt32(exec, ok); - if (!ok) - return jsUndefined(); - - RefPtr<InspectorResource> resource = impl()->resources().get(identifier); - ASSERT(resource); - if (!resource) - return jsUndefined(); - - Frame* frame = resource->frame(); - Document* document = frame->document(); - - if (document->isPluginDocument() || document->isImageDocument() || document->isMediaDocument()) - return jsUndefined(); - - ExecState* resourceExec = toJSDOMWindowShell(frame)->window()->globalExec(); - - JSLock lock(false); - return JSInspectedObjectWrapper::wrap(resourceExec, toJS(resourceExec, document)); -} - -JSValue JSInspectorController::search(ExecState* exec, const ArgList& args) +JSValue JSInspectorBackend::search(ExecState* exec, const ArgList& args) { if (args.size() < 2) return jsUndefined(); @@ -151,7 +125,7 @@ JSValue JSInspectorController::search(ExecState* exec, const ArgList& args) } #if ENABLE(DATABASE) -JSValue JSInspectorController::databaseTableNames(ExecState* exec, const ArgList& args) +JSValue JSInspectorBackend::databaseTableNames(ExecState* exec, const ArgList& args) { if (args.size() < 1) return jsUndefined(); @@ -175,13 +149,16 @@ JSValue JSInspectorController::databaseTableNames(ExecState* exec, const ArgList } #endif -JSValue JSInspectorController::inspectedWindow(ExecState*, const ArgList&) +JSValue JSInspectorBackend::inspectedWindow(ExecState*, const ArgList&) { - JSDOMWindow* inspectedWindow = toJSDOMWindow(impl()->inspectedPage()->mainFrame()); + InspectorController* ic = impl()->inspectorController(); + if (!ic) + return jsUndefined(); + JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame()); return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), inspectedWindow); } -JSValue JSInspectorController::setting(ExecState* exec, const ArgList& args) +JSValue JSInspectorBackend::setting(ExecState* exec, const ArgList& args) { if (args.size() < 1) return jsUndefined(); @@ -190,7 +167,10 @@ JSValue JSInspectorController::setting(ExecState* exec, const ArgList& args) if (exec->hadException()) return jsUndefined(); - const InspectorController::Setting& setting = impl()->setting(key); + InspectorController* ic = impl()->inspectorController(); + if (!ic) + return jsUndefined(); + const InspectorController::Setting& setting = ic->setting(key); switch (setting.type()) { default: @@ -215,7 +195,7 @@ JSValue JSInspectorController::setting(ExecState* exec, const ArgList& args) } } -JSValue JSInspectorController::setSetting(ExecState* exec, const ArgList& args) +JSValue JSInspectorBackend::setSetting(ExecState* exec, const ArgList& args) { if (args.size() < 2) return jsUndefined(); @@ -253,12 +233,14 @@ JSValue JSInspectorController::setSetting(ExecState* exec, const ArgList& args) if (exec->hadException()) return jsUndefined(); - impl()->setSetting(key, setting); + InspectorController* ic = impl()->inspectorController(); + if (ic) + ic->setSetting(key, setting); return jsUndefined(); } -JSValue JSInspectorController::wrapCallback(ExecState* exec, const ArgList& args) +JSValue JSInspectorBackend::wrapCallback(ExecState* exec, const ArgList& args) { if (args.size() < 1) return jsUndefined(); @@ -268,7 +250,7 @@ JSValue JSInspectorController::wrapCallback(ExecState* exec, const ArgList& args #if ENABLE(JAVASCRIPT_DEBUGGER) -JSValue JSInspectorController::currentCallFrame(ExecState* exec, const ArgList&) +JSValue JSInspectorBackend::currentCallFrame(ExecState* exec, const ArgList&) { JavaScriptCallFrame* callFrame = impl()->currentCallFrame(); if (!callFrame || !callFrame->isValid()) @@ -277,15 +259,18 @@ JSValue JSInspectorController::currentCallFrame(ExecState* exec, const ArgList&) // FIXME: I am not sure if this is actually needed. Can we just use exec? ExecState* globalExec = callFrame->scopeChain()->globalObject()->globalExec(); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); return JSInspectedObjectWrapper::wrap(globalExec, toJS(exec, callFrame)); } -JSValue JSInspectorController::profiles(JSC::ExecState* exec, const JSC::ArgList&) +JSValue JSInspectorBackend::profiles(JSC::ExecState* exec, const JSC::ArgList&) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); MarkedArgumentBuffer result; - const Vector<RefPtr<Profile> >& profiles = impl()->profiles(); + InspectorController* ic = impl()->inspectorController(); + if (!ic) + return jsUndefined(); + const Vector<RefPtr<Profile> >& profiles = ic->profiles(); for (size_t i = 0; i < profiles.size(); ++i) result.append(toJS(exec, profiles[i].get())); diff --git a/WebCore/bindings/js/JSLazyEventListener.cpp b/WebCore/bindings/js/JSLazyEventListener.cpp index f7c74ae..7caff2b 100644 --- a/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/WebCore/bindings/js/JSLazyEventListener.cpp @@ -77,7 +77,11 @@ void JSLazyEventListener::parseCode() const if (m_parsed) return; - if (m_globalObject->scriptExecutionContext()->isDocument()) { + ScriptExecutionContext* executionContext = m_globalObject->scriptExecutionContext(); + ASSERT(executionContext); + if (!executionContext) + return; + if (executionContext->isDocument()) { JSDOMWindow* window = static_cast<JSDOMWindow*>(m_globalObject); Frame* frame = window->impl()->frame(); if (!frame) @@ -93,7 +97,7 @@ void JSLazyEventListener::parseCode() const ExecState* exec = m_globalObject->globalExec(); MarkedArgumentBuffer args; - UString sourceURL(m_globalObject->scriptExecutionContext()->url().string()); + UString sourceURL(executionContext->url().string()); args.append(jsNontrivialString(exec, m_eventParameterName)); args.append(jsString(exec, m_code)); @@ -113,7 +117,7 @@ void JSLazyEventListener::parseCode() const // (and the document, and the form - see JSHTMLElement::eventHandlerScope) ScopeChain scope = listenerAsFunction->scope(); - JSValue thisObj = toJS(exec, m_originalNode); + JSValue thisObj = toJS(exec, m_globalObject, m_originalNode); if (thisObj.isObject()) { static_cast<JSNode*>(asObject(thisObj))->pushEventHandlerScope(exec, scope); listenerAsFunction->setScope(scope); diff --git a/WebCore/bindings/js/JSLocationCustom.cpp b/WebCore/bindings/js/JSLocationCustom.cpp index 9c5a834..d7d32f4 100644 --- a/WebCore/bindings/js/JSLocationCustom.cpp +++ b/WebCore/bindings/js/JSLocationCustom.cpp @@ -39,20 +39,20 @@ namespace WebCore { static JSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) { - return new (exec) PrototypeFunction(exec, 1, propertyName, jsLocationPrototypeFunctionReplace); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionReplace); } static JSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) { - return new (exec) PrototypeFunction(exec, 0, propertyName, jsLocationPrototypeFunctionReload); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsLocationPrototypeFunctionReload); } static JSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) { - return new (exec) PrototypeFunction(exec, 1, propertyName, jsLocationPrototypeFunctionAssign); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionAssign); } -bool JSLocation::customGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { Frame* frame = impl()->frame(); if (!frame) { @@ -61,7 +61,7 @@ bool JSLocation::customGetOwnPropertySlot(ExecState* exec, const Identifier& pro } // When accessing Location cross-domain, functions are always the native built-in ones. - // See JSDOMWindow::customGetOwnPropertySlot for additional details. + // See JSDOMWindow::getOwnPropertySlotDelegate for additional details. // Our custom code is only needed to implement the Window cross-domain scheme, so if access is // allowed, return false so the normal lookup will take place. @@ -93,7 +93,7 @@ bool JSLocation::customGetOwnPropertySlot(ExecState* exec, const Identifier& pro return true; } -bool JSLocation::customPut(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +bool JSLocation::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { Frame* frame = impl()->frame(); if (!frame) @@ -128,12 +128,12 @@ bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName) return Base::deleteProperty(exec, propertyName); } -bool JSLocation::customGetPropertyNames(ExecState* exec, PropertyNameArray&) +void JSLocation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) { // Only allow the location object to enumerated by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) - return true; - return false; + return; + Base::getPropertyNames(exec, propertyNames); } void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction) @@ -245,13 +245,13 @@ void JSLocation::setHash(ExecState* exec, JSValue value) ASSERT(frame); KURL url = frame->loader()->url(); - String oldRef = url.ref(); + String oldFragmentIdentifier = url.fragmentIdentifier(); String str = value.toString(exec); if (str.startsWith("#")) str = str.substring(1); - if (oldRef == str || (oldRef.isNull() && str.isEmpty())) + if (equalIgnoringNullity(oldFragmentIdentifier, str)) return; - url.setRef(str); + url.setFragmentIdentifier(str); navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false); } @@ -311,7 +311,7 @@ JSValue JSLocation::toString(ExecState* exec, const ArgList&) return jsString(exec, impl()->toString()); } -bool JSLocationPrototype::customPut(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&) +bool JSLocationPrototype::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&) { return (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf); } diff --git a/WebCore/bindings/js/JSMessageChannelConstructor.cpp b/WebCore/bindings/js/JSMessageChannelConstructor.cpp index 495bd53..25a5cb2 100644 --- a/WebCore/bindings/js/JSMessageChannelConstructor.cpp +++ b/WebCore/bindings/js/JSMessageChannelConstructor.cpp @@ -38,21 +38,15 @@ namespace WebCore { const ClassInfo JSMessageChannelConstructor::s_info = { "MessageChannelConstructor", 0, 0, 0 }; JSMessageChannelConstructor::JSMessageChannelConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMObject(JSMessageChannelConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) - , m_globalObject(globalObject) + : DOMConstructorObject(JSMessageChannelConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - putDirect(exec->propertyNames().prototype, JSMessageChannelPrototype::self(exec, exec->lexicalGlobalObject()), None); + putDirect(exec->propertyNames().prototype, JSMessageChannelPrototype::self(exec, globalObject), None); } JSMessageChannelConstructor::~JSMessageChannelConstructor() { } -ScriptExecutionContext* JSMessageChannelConstructor::scriptExecutionContext() const -{ - return m_globalObject->scriptExecutionContext(); -} - ConstructType JSMessageChannelConstructor::getConstructData(ConstructData& constructData) { constructData.native.function = construct; @@ -61,18 +55,12 @@ ConstructType JSMessageChannelConstructor::getConstructData(ConstructData& const JSObject* JSMessageChannelConstructor::construct(ExecState* exec, JSObject* constructor, const ArgList&) { - ScriptExecutionContext* context = static_cast<JSMessageChannelConstructor*>(constructor)->scriptExecutionContext(); + JSMessageChannelConstructor* jsConstructor = static_cast<JSMessageChannelConstructor*>(constructor); + ScriptExecutionContext* context = jsConstructor->scriptExecutionContext(); if (!context) return throwError(exec, ReferenceError, "MessageChannel constructor associated document is unavailable"); - return asObject(toJS(exec, MessageChannel::create(context))); -} - -void JSMessageChannelConstructor::mark() -{ - DOMObject::mark(); - if (!m_globalObject->marked()) - m_globalObject->mark(); + return asObject(toJS(exec, jsConstructor->globalObject(), MessageChannel::create(context))); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSMessageChannelConstructor.h b/WebCore/bindings/js/JSMessageChannelConstructor.h index 90c29a3..d958760 100644 --- a/WebCore/bindings/js/JSMessageChannelConstructor.h +++ b/WebCore/bindings/js/JSMessageChannelConstructor.h @@ -30,23 +30,16 @@ namespace WebCore { - class JSMessageChannelConstructor : public DOMObject { + class JSMessageChannelConstructor : public DOMConstructorObject { public: JSMessageChannelConstructor(JSC::ExecState*, JSDOMGlobalObject*); virtual ~JSMessageChannelConstructor(); virtual const JSC::ClassInfo* classInfo() const { return &s_info; } static const JSC::ClassInfo s_info; - ScriptExecutionContext* scriptExecutionContext() const; - virtual bool implementsHasInstance() const { return true; } static JSC::JSObject* construct(JSC::ExecState*, JSC::JSObject*, const JSC::ArgList&); virtual JSC::ConstructType getConstructData(JSC::ConstructData&); - - virtual void mark(); - - private: - JSDOMGlobalObject* m_globalObject; }; } // namespace WebCore diff --git a/WebCore/bindings/js/JSMessageChannelCustom.cpp b/WebCore/bindings/js/JSMessageChannelCustom.cpp index 70329e2..574e28a 100644 --- a/WebCore/bindings/js/JSMessageChannelCustom.cpp +++ b/WebCore/bindings/js/JSMessageChannelCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,20 +32,20 @@ using namespace JSC; namespace WebCore { -void JSMessageChannel::mark() +void JSMessageChannel::markChildren(MarkStack& markStack) { - DOMObject::mark(); + Base::markChildren(markStack); if (MessagePort* port = m_impl->port1()) { DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port); - if (wrapper && !wrapper->marked()) - wrapper->mark(); + if (wrapper) + markStack.append(wrapper); } if (MessagePort* port = m_impl->port2()) { DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port); - if (wrapper && !wrapper->marked()) - wrapper->mark(); + if (wrapper) + markStack.append(wrapper); } } diff --git a/WebCore/bindings/js/JSMessagePortCustom.cpp b/WebCore/bindings/js/JSMessagePortCustom.cpp index f4809ae..c3316c5 100644 --- a/WebCore/bindings/js/JSMessagePortCustom.cpp +++ b/WebCore/bindings/js/JSMessagePortCustom.cpp @@ -38,17 +38,17 @@ using namespace JSC; namespace WebCore { -void JSMessagePort::mark() +void JSMessagePort::markChildren(MarkStack& markStack) { - DOMObject::mark(); + Base::markChildren(markStack); - markIfNotNull(m_impl->onmessage()); - markIfNotNull(m_impl->onclose()); + markIfNotNull(markStack, m_impl->onmessage()); - if (MessagePortProxy* entangledPort = m_impl->entangledPort()) { + // If we have a locally entangled port, we can directly mark it as reachable. Ports that are remotely entangled are marked in-use by markActiveObjectsForContext(). + if (MessagePort* entangledPort = m_impl->locallyEntangledPort()) { DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), entangledPort); - if (wrapper && !wrapper->marked()) - wrapper->mark(); + if (wrapper) + markStack.append(wrapper); } typedef MessagePort::EventListenersMap EventListenersMap; @@ -56,18 +56,10 @@ void JSMessagePort::mark() EventListenersMap& eventListeners = m_impl->eventListeners(); for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) { for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) - (*vecIter)->markJSFunction(); + (*vecIter)->markJSFunction(markStack); } } -JSValue JSMessagePort::startConversation(ExecState* exec, const ArgList& args) -{ - JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); - const UString& message = args.at(0).toString(exec); - - return toJS(exec, impl()->startConversation(globalObject->scriptExecutionContext(), message).get()); -} - JSValue JSMessagePort::addEventListener(ExecState* exec, const ArgList& args) { JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext()); diff --git a/WebCore/bindings/js/JSNamedNodesCollection.cpp b/WebCore/bindings/js/JSNamedNodesCollection.cpp index 93a8937..f36a7d6 100644 --- a/WebCore/bindings/js/JSNamedNodesCollection.cpp +++ b/WebCore/bindings/js/JSNamedNodesCollection.cpp @@ -42,8 +42,8 @@ const ClassInfo JSNamedNodesCollection::s_info = { "Collection", 0, 0, 0 }; // Such a collection is usually very short-lived, it only exists // for constructs like document.forms.<name>[1], // so it shouldn't be a problem that it's storing all the nodes (with the same name). (David) -JSNamedNodesCollection::JSNamedNodesCollection(ExecState* exec, const Vector<RefPtr<Node> >& nodes) - : DOMObject(getDOMStructure<JSNamedNodesCollection>(exec)) +JSNamedNodesCollection::JSNamedNodesCollection(ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<RefPtr<Node> >& nodes) + : DOMObjectWithGlobalPointer(getDOMStructure<JSNamedNodesCollection>(exec, globalObject), globalObject) , m_nodes(new Vector<RefPtr<Node> >(nodes)) { } @@ -86,7 +86,7 @@ bool JSNamedNodesCollection::getOwnPropertySlot(ExecState* exec, const Identifie } } - return DOMObject::getOwnPropertySlot(exec, propertyName, slot); + return DOMObjectWithGlobalPointer::getOwnPropertySlot(exec, propertyName, slot); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSNamedNodesCollection.h b/WebCore/bindings/js/JSNamedNodesCollection.h index 3bbc102..cd6c2cb 100644 --- a/WebCore/bindings/js/JSNamedNodesCollection.h +++ b/WebCore/bindings/js/JSNamedNodesCollection.h @@ -35,9 +35,9 @@ namespace WebCore { // Internal class, used for the collection return by e.g. document.forms.myinput // when multiple nodes have the same name. - class JSNamedNodesCollection : public DOMObject { + class JSNamedNodesCollection : public DOMObjectWithGlobalPointer { public: - JSNamedNodesCollection(JSC::ExecState*, const Vector<RefPtr<Node> >&); + JSNamedNodesCollection(JSC::ExecState*, JSDOMGlobalObject*, const Vector<RefPtr<Node> >&); virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); diff --git a/WebCore/bindings/js/JSNavigatorCustom.cpp b/WebCore/bindings/js/JSNavigatorCustom.cpp index ea6cceb..c023931 100644 --- a/WebCore/bindings/js/JSNavigatorCustom.cpp +++ b/WebCore/bindings/js/JSNavigatorCustom.cpp @@ -29,13 +29,13 @@ namespace WebCore { using namespace JSC; -void JSNavigator::mark() +void JSNavigator::markChildren(MarkStack& markStack) { - Base::mark(); + Base::markChildren(markStack); JSGlobalData& globalData = *Heap::heap(this)->globalData(); - markDOMObjectWrapper(globalData, impl()->optionalGeolocation()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalGeolocation()); } } diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp index 79ac6b7..cf884b9 100644 --- a/WebCore/bindings/js/JSNodeCustom.cpp +++ b/WebCore/bindings/js/JSNodeCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -110,7 +110,7 @@ JSValue JSNode::appendChild(ExecState* exec, const ArgList& args) JSValue JSNode::addEventListener(ExecState* exec, const ArgList& args) { - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext()); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->document()); if (!globalObject) return jsUndefined(); @@ -122,7 +122,7 @@ JSValue JSNode::addEventListener(ExecState* exec, const ArgList& args) JSValue JSNode::removeEventListener(ExecState* exec, const ArgList& args) { - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext()); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->document()); if (!globalObject) return jsUndefined(); @@ -136,22 +136,21 @@ void JSNode::pushEventHandlerScope(ExecState*, ScopeChain&) const { } -void JSNode::mark() +void JSNode::markChildren(MarkStack& markStack) { - ASSERT(!marked()); - Node* node = m_impl.get(); + Base::markChildren(markStack); + markEventListeners(markStack, node->eventListeners()); + // Nodes in the document are kept alive by JSDocument::mark, so, if we're in // the document, we need to mark the document, but we don't need to explicitly // mark any other nodes. if (node->inDocument()) { - DOMObject::mark(); - markEventListeners(node->eventListeners()); - if (Document* doc = node->ownerDocument()) + if (Document* doc = node->ownerDocument()) { if (DOMObject* docWrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), doc)) - if (!docWrapper->marked()) - docWrapper->mark(); + markStack.append(docWrapper); + } return; } @@ -163,36 +162,20 @@ void JSNode::mark() // Nodes in a subtree are marked by the tree's root, so, if the root is already // marking the tree, we don't need to explicitly mark any other nodes. - if (root->inSubtreeMark()) { - DOMObject::mark(); - markEventListeners(node->eventListeners()); + if (root->inSubtreeMark()) return; - } // Mark the whole tree subtree. root->setInSubtreeMark(true); for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) { JSNode* wrapper = getCachedDOMNodeWrapper(m_impl->document(), nodeToMark); - if (wrapper) { - if (!wrapper->marked()) - wrapper->mark(); - } else if (nodeToMark == node) { - // This is the case where the map from the document to wrappers has - // been cleared out, but a wrapper is being marked. For now, we'll - // let the rest of the tree of wrappers get collected, because we have - // no good way of finding them. Later we should test behavior of other - // browsers and see if we need to preserve other wrappers in this case. - if (!marked()) - mark(); - } + if (wrapper) + markStack.append(wrapper); } root->setInSubtreeMark(false); - - // Double check that we actually ended up marked. This assert caught problems in the past. - ASSERT(marked()); } -static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, Node* node) +static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) { ASSERT(node); ASSERT(!getCachedDOMNodeWrapper(node->document(), node)); @@ -201,63 +184,63 @@ static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, Node* node) switch (node->nodeType()) { case Node::ELEMENT_NODE: if (node->isHTMLElement()) - wrapper = createJSHTMLWrapper(exec, static_cast<HTMLElement*>(node)); + wrapper = createJSHTMLWrapper(exec, globalObject, static_cast<HTMLElement*>(node)); #if ENABLE(SVG) else if (node->isSVGElement()) - wrapper = createJSSVGWrapper(exec, static_cast<SVGElement*>(node)); + wrapper = createJSSVGWrapper(exec, globalObject, static_cast<SVGElement*>(node)); #endif else - wrapper = CREATE_DOM_NODE_WRAPPER(exec, Element, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Element, node); break; case Node::ATTRIBUTE_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, Attr, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Attr, node); break; case Node::TEXT_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, Text, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Text, node); break; case Node::CDATA_SECTION_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, CDATASection, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, CDATASection, node); break; case Node::ENTITY_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, Entity, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Entity, node); break; case Node::PROCESSING_INSTRUCTION_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, ProcessingInstruction, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, ProcessingInstruction, node); break; case Node::COMMENT_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, Comment, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Comment, node); break; case Node::DOCUMENT_NODE: // we don't want to cache the document itself in the per-document dictionary - return toJS(exec, static_cast<Document*>(node)); + return toJS(exec, globalObject, static_cast<Document*>(node)); case Node::DOCUMENT_TYPE_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, DocumentType, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, DocumentType, node); break; case Node::NOTATION_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, Notation, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Notation, node); break; case Node::DOCUMENT_FRAGMENT_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, DocumentFragment, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, DocumentFragment, node); break; case Node::ENTITY_REFERENCE_NODE: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, EntityReference, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, EntityReference, node); break; default: - wrapper = CREATE_DOM_NODE_WRAPPER(exec, Node, node); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Node, node); } return wrapper; } -JSValue toJSNewlyCreated(ExecState* exec, Node* node) +JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) { if (!node) return jsNull(); - return createWrapper(exec, node); + return createWrapper(exec, globalObject, node); } -JSValue toJS(ExecState* exec, Node* node) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) { if (!node) return jsNull(); @@ -266,7 +249,7 @@ JSValue toJS(ExecState* exec, Node* node) if (wrapper) return wrapper; - return createWrapper(exec, node); + return createWrapper(exec, globalObject, node); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSNodeFilterCondition.cpp b/WebCore/bindings/js/JSNodeFilterCondition.cpp index f5d4d5c..a199417 100644 --- a/WebCore/bindings/js/JSNodeFilterCondition.cpp +++ b/WebCore/bindings/js/JSNodeFilterCondition.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,15 +36,14 @@ JSNodeFilterCondition::JSNodeFilterCondition(JSValue filter) { } -void JSNodeFilterCondition::mark() +void JSNodeFilterCondition::markAggregate(MarkStack& markStack) { - if (!m_filter.marked()) - m_filter.mark(); + markStack.append(m_filter); } short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) const { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); CallData callData; CallType callType = m_filter.getCallData(callData); @@ -61,7 +60,9 @@ short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) return NodeFilter::FILTER_REJECT; MarkedArgumentBuffer args; - args.append(toJS(exec, filterNode)); + // FIXME: The node should have the prototype chain that came from its document, not + // whatever prototype chain might be on the window this filter came from. Bug 27662 + args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), filterNode)); if (exec->hadException()) return NodeFilter::FILTER_REJECT; diff --git a/WebCore/bindings/js/JSNodeFilterCondition.h b/WebCore/bindings/js/JSNodeFilterCondition.h index 3d591c6..b96534a 100644 --- a/WebCore/bindings/js/JSNodeFilterCondition.h +++ b/WebCore/bindings/js/JSNodeFilterCondition.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,7 +39,7 @@ namespace WebCore { JSNodeFilterCondition(JSC::JSValue filter); virtual short acceptNode(ScriptState*, Node*) const; - virtual void mark(); + virtual void markAggregate(JSC::MarkStack&); mutable JSC::JSValue m_filter; }; diff --git a/WebCore/bindings/js/JSNodeFilterCustom.cpp b/WebCore/bindings/js/JSNodeFilterCustom.cpp index ecc12d5..09fd110 100644 --- a/WebCore/bindings/js/JSNodeFilterCustom.cpp +++ b/WebCore/bindings/js/JSNodeFilterCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,10 +35,10 @@ using namespace JSC; namespace WebCore { -void JSNodeFilter::mark() +void JSNodeFilter::markChildren(MarkStack& markStack) { - impl()->mark(); - DOMObject::mark(); + Base::markChildren(markStack); + impl()->markAggregate(markStack); } JSValue JSNodeFilter::acceptNode(ExecState* exec, const ArgList& args) diff --git a/WebCore/bindings/js/JSNodeIteratorCustom.cpp b/WebCore/bindings/js/JSNodeIteratorCustom.cpp index 8fff82e..6a09abf 100644 --- a/WebCore/bindings/js/JSNodeIteratorCustom.cpp +++ b/WebCore/bindings/js/JSNodeIteratorCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,12 +29,12 @@ using namespace JSC; namespace WebCore { -void JSNodeIterator::mark() +void JSNodeIterator::markChildren(MarkStack& markStack) { + Base::markChildren(markStack); + if (NodeFilter* filter = m_impl->filter()) - filter->mark(); - - DOMObject::mark(); + filter->markAggregate(markStack); } JSValue JSNodeIterator::nextNode(ExecState* exec, const ArgList&) diff --git a/WebCore/bindings/js/JSOptionConstructor.cpp b/WebCore/bindings/js/JSOptionConstructor.cpp index 9e818ff..2b8bd5d 100644 --- a/WebCore/bindings/js/JSOptionConstructor.cpp +++ b/WebCore/bindings/js/JSOptionConstructor.cpp @@ -35,24 +35,16 @@ ASSERT_CLASS_FITS_IN_CELL(JSOptionConstructor); const ClassInfo JSOptionConstructor::s_info = { "OptionConstructor", 0, 0, 0 }; JSOptionConstructor::JSOptionConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMObject(JSOptionConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) - , m_globalObject(globalObject) + : DOMConstructorWithDocument(JSOptionConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - ASSERT(globalObject->scriptExecutionContext()); - ASSERT(globalObject->scriptExecutionContext()->isDocument()); - - putDirect(exec->propertyNames().prototype, JSHTMLOptionElementPrototype::self(exec, exec->lexicalGlobalObject()), None); + putDirect(exec->propertyNames().prototype, JSHTMLOptionElementPrototype::self(exec, globalObject), None); putDirect(exec->propertyNames().length, jsNumber(exec, 4), ReadOnly|DontDelete|DontEnum); } -Document* JSOptionConstructor::document() const -{ - return static_cast<Document*>(m_globalObject->scriptExecutionContext()); -} - static JSObject* constructHTMLOptionElement(ExecState* exec, JSObject* constructor, const ArgList& args) { - Document* document = static_cast<JSOptionConstructor*>(constructor)->document(); + JSOptionConstructor* jsConstructor = static_cast<JSOptionConstructor*>(constructor); + Document* document = jsConstructor->document(); if (!document) return throwError(exec, ReferenceError, "Option constructor associated document is unavailable"); @@ -76,7 +68,7 @@ static JSObject* constructHTMLOptionElement(ExecState* exec, JSObject* construct return 0; } - return asObject(toJS(exec, element.release())); + return asObject(toJS(exec, jsConstructor->globalObject(), element.release())); } ConstructType JSOptionConstructor::getConstructData(ConstructData& constructData) @@ -85,11 +77,5 @@ ConstructType JSOptionConstructor::getConstructData(ConstructData& constructData return ConstructTypeHost; } -void JSOptionConstructor::mark() -{ - DOMObject::mark(); - if (!m_globalObject->marked()) - m_globalObject->mark(); -} } // namespace WebCore diff --git a/WebCore/bindings/js/JSOptionConstructor.h b/WebCore/bindings/js/JSOptionConstructor.h index 3c87c28..246e7fa 100644 --- a/WebCore/bindings/js/JSOptionConstructor.h +++ b/WebCore/bindings/js/JSOptionConstructor.h @@ -26,19 +26,14 @@ namespace WebCore { - class JSOptionConstructor : public DOMObject { + class JSOptionConstructor : public DOMConstructorWithDocument { public: JSOptionConstructor(JSC::ExecState*, JSDOMGlobalObject*); - Document* document() const; static const JSC::ClassInfo s_info; - - virtual void mark(); private: virtual JSC::ConstructType getConstructData(JSC::ConstructData&); virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - - JSDOMGlobalObject* m_globalObject; }; } // namespace WebCore diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp b/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp index ad1e556..5f4dfd4 100644 --- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp +++ b/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -92,14 +92,12 @@ void JSQuarantinedObjectWrapper::transferExceptionToExecState(ExecState* exec) c exec->setException(wrapOutgoingValue(unwrappedExecState(), exception)); } -void JSQuarantinedObjectWrapper::mark() +void JSQuarantinedObjectWrapper::markChildren(MarkStack& markStack) { - JSObject::mark(); + JSObject::markChildren(markStack); - if (!m_unwrappedObject->marked()) - m_unwrappedObject->mark(); - if (!m_unwrappedGlobalObject->marked()) - m_unwrappedGlobalObject->mark(); + markStack.append(m_unwrappedObject); + markStack.append(m_unwrappedGlobalObject); } bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot) diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h b/WebCore/bindings/js/JSQuarantinedObjectWrapper.h index bf8fddb..08935e7 100644 --- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h +++ b/WebCore/bindings/js/JSQuarantinedObjectWrapper.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,7 +53,7 @@ namespace WebCore { protected: JSQuarantinedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, PassRefPtr<JSC::Structure>); - virtual void mark(); + virtual void markChildren(JSC::MarkStack&); private: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); diff --git a/WebCore/bindings/js/JSRGBColor.cpp b/WebCore/bindings/js/JSRGBColor.cpp deleted file mode 100644 index f7c87e2..0000000 --- a/WebCore/bindings/js/JSRGBColor.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2000 Harri Porten (porten@kde.org) - * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2006 James G. Speth (speth@end.com) - * Copyright (C) 2006 Samuel Weinig (sam@webkit.org) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 "config.h" -#include "JSRGBColor.h" - -#include "CSSPrimitiveValue.h" -#include "JSCSSPrimitiveValue.h" - -using namespace JSC; - -static JSValue jsRGBColorRed(ExecState*, const Identifier&, const PropertySlot&); -static JSValue jsRGBColorGreen(ExecState*, const Identifier&, const PropertySlot&); -static JSValue jsRGBColorBlue(ExecState*, const Identifier&, const PropertySlot&); - -/* -@begin JSRGBColorTable - red jsRGBColorRed DontDelete|ReadOnly - green jsRGBColorGreen DontDelete|ReadOnly - blue jsRGBColorBlue DontDelete|ReadOnly -@end -*/ - -#include "JSRGBColor.lut.h" - -namespace WebCore { - -ASSERT_CLASS_FITS_IN_CELL(JSRGBColor); - -const ClassInfo JSRGBColor::s_info = { "RGBColor", 0, &JSRGBColorTable, 0 }; - -JSRGBColor::JSRGBColor(ExecState* exec, unsigned color) - : DOMObject(getDOMStructure<JSRGBColor>(exec)) - , m_color(color) -{ -} - -bool JSRGBColor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) -{ - return getStaticValueSlot<JSRGBColor, DOMObject>(exec, &JSRGBColorTable, this, propertyName, slot); -} - -JSValue getJSRGBColor(ExecState* exec, unsigned color) -{ - return new (exec) JSRGBColor(exec, color); -} - -} // namespace WebCore - -using namespace WebCore; - -JSValue jsRGBColorRed(ExecState* exec, const Identifier&, const PropertySlot& slot) -{ - return toJS(exec, CSSPrimitiveValue::create((static_cast<JSRGBColor*>(asObject(slot.slotBase()))->impl() >> 16) & 0xFF, CSSPrimitiveValue::CSS_NUMBER)); -} - -JSValue jsRGBColorGreen(ExecState* exec, const Identifier&, const PropertySlot& slot) -{ - return toJS(exec, CSSPrimitiveValue::create((static_cast<JSRGBColor*>(asObject(slot.slotBase()))->impl() >> 8) & 0xFF, CSSPrimitiveValue::CSS_NUMBER)); -} - -JSValue jsRGBColorBlue(ExecState* exec, const Identifier&, const PropertySlot& slot) -{ - return toJS(exec, CSSPrimitiveValue::create(static_cast<JSRGBColor*>(asObject(slot.slotBase()))->impl() & 0xFF, CSSPrimitiveValue::CSS_NUMBER)); -} - diff --git a/WebCore/bindings/js/JSRGBColor.h b/WebCore/bindings/js/JSRGBColor.h deleted file mode 100644 index cc2870f..0000000 --- a/WebCore/bindings/js/JSRGBColor.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2000 Harri Porten (porten@kde.org) - * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - */ - -#ifndef JSRGBColor_h -#define JSRGBColor_h - -#include "Color.h" -#include "JSDOMBinding.h" - -namespace WebCore { - - // FIXME: JSRGBColor should have a proper prototype and a constructor. - class JSRGBColor : public DOMObject { - public: - JSRGBColor(JSC::ExecState*, unsigned color); - - virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); - - virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - static const JSC::ClassInfo s_info; - - unsigned impl() const { return m_color; } - - static JSC::ObjectPrototype* createPrototype(JSC::ExecState*, JSC::JSGlobalObject* globalObject) - { - return globalObject->objectPrototype(); - } - - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) - { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); - } - - private: - unsigned m_color; - }; - - JSC::JSValue getJSRGBColor(JSC::ExecState*, unsigned color); - -} // namespace WebCore - -#endif // JSRGBColor_h diff --git a/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp b/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp index 2922740..6e77f9b 100644 --- a/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp +++ b/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2009 Apple, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,14 +38,14 @@ using namespace JSC; namespace WebCore { -void JSSVGElementInstance::mark() +void JSSVGElementInstance::markChildren(MarkStack& markStack) { - DOMObject::mark(); + Base::markChildren(markStack); // Mark the wrapper for our corresponding element, so it can mark its event handlers. JSNode* correspondingWrapper = getCachedDOMNodeWrapper(impl()->correspondingElement()->document(), impl()->correspondingElement()); - if (correspondingWrapper && !correspondingWrapper->marked()) - correspondingWrapper->mark(); + if (correspondingWrapper) + markStack.append(correspondingWrapper); } JSValue JSSVGElementInstance::addEventListener(ExecState* exec, const ArgList& args) @@ -75,9 +76,9 @@ void JSSVGElementInstance::pushEventHandlerScope(ExecState*, ScopeChain&) const { } -JSC::JSValue toJS(JSC::ExecState* exec, SVGElementInstance* object) +JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, SVGElementInstance* object) { - JSValue result = getDOMObjectWrapper<JSSVGElementInstance>(exec, object); + JSValue result = getDOMObjectWrapper<JSSVGElementInstance>(exec, globalObject, object); // Ensure that our corresponding element has a JavaScript wrapper to keep its event handlers alive. if (object) diff --git a/WebCore/bindings/js/JSSVGMatrixCustom.cpp b/WebCore/bindings/js/JSSVGMatrixCustom.cpp index fc1e266..35390b2 100644 --- a/WebCore/bindings/js/JSSVGMatrixCustom.cpp +++ b/WebCore/bindings/js/JSSVGMatrixCustom.cpp @@ -32,7 +32,7 @@ namespace WebCore { JSValue JSSVGMatrix::inverse(ExecState* exec, const ArgList&) { TransformationMatrix imp(*impl()); - JSC::JSValue result = toJS(exec, JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.inverse()).get(), m_context.get()); + JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.inverse()).get(), m_context.get()); if (!imp.isInvertible()) setDOMException(exec, SVGException::SVG_MATRIX_NOT_INVERTABLE); @@ -47,7 +47,7 @@ JSValue JSSVGMatrix::rotateFromVector(ExecState* exec, const ArgList& args) float x = args.at(0).toFloat(exec); float y = args.at(1).toFloat(exec); - JSC::JSValue result = toJS(exec, JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.rotateFromVector(x, y)).get(), m_context.get()); + JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.rotateFromVector(x, y)).get(), m_context.get()); if (x == 0.0 || y == 0.0) setDOMException(exec, SVGException::SVG_INVALID_VALUE_ERR); diff --git a/WebCore/bindings/js/JSSVGPathSegCustom.cpp b/WebCore/bindings/js/JSSVGPathSegCustom.cpp index cb4687c..42fa878 100644 --- a/WebCore/bindings/js/JSSVGPathSegCustom.cpp +++ b/WebCore/bindings/js/JSSVGPathSegCustom.cpp @@ -59,7 +59,7 @@ using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, SVGPathSeg* object, SVGElement* context) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, SVGPathSeg* object, SVGElement* context) { if (!object) return jsNull(); @@ -69,46 +69,46 @@ JSValue toJS(ExecState* exec, SVGPathSeg* object, SVGElement* context) switch (object->pathSegType()) { case SVGPathSeg::PATHSEG_CLOSEPATH: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegClosePath, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegClosePath, object, context); case SVGPathSeg::PATHSEG_MOVETO_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegMovetoAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegMovetoAbs, object, context); case SVGPathSeg::PATHSEG_MOVETO_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegMovetoRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegMovetoRel, object, context); case SVGPathSeg::PATHSEG_LINETO_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegLinetoAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegLinetoAbs, object, context); case SVGPathSeg::PATHSEG_LINETO_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegLinetoRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegLinetoRel, object, context); case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegCurvetoCubicAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicAbs, object, context); case SVGPathSeg::PATHSEG_CURVETO_CUBIC_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegCurvetoCubicRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicRel, object, context); case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegCurvetoQuadraticAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticAbs, object, context); case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegCurvetoQuadraticRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticRel, object, context); case SVGPathSeg::PATHSEG_ARC_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegArcAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegArcAbs, object, context); case SVGPathSeg::PATHSEG_ARC_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegArcRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegArcRel, object, context); case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegLinetoHorizontalAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegLinetoHorizontalAbs, object, context); case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegLinetoHorizontalRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegLinetoHorizontalRel, object, context); case SVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegLinetoVerticalAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegLinetoVerticalAbs, object, context); case SVGPathSeg::PATHSEG_LINETO_VERTICAL_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegLinetoVerticalRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegLinetoVerticalRel, object, context); case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegCurvetoCubicSmoothAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicSmoothAbs, object, context); case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegCurvetoCubicSmoothRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicSmoothRel, object, context); case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegCurvetoQuadraticSmoothAbs, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticSmoothAbs, object, context); case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSegCurvetoQuadraticSmoothRel, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticSmoothRel, object, context); case SVGPathSeg::PATHSEG_UNKNOWN: default: - return CREATE_SVG_OBJECT_WRAPPER(exec, SVGPathSeg, object, context); + return CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, SVGPathSeg, object, context); } } diff --git a/WebCore/bindings/js/JSSVGPathSegListCustom.cpp b/WebCore/bindings/js/JSSVGPathSegListCustom.cpp index b6fc116..b71f3a6 100644 --- a/WebCore/bindings/js/JSSVGPathSegListCustom.cpp +++ b/WebCore/bindings/js/JSSVGPathSegListCustom.cpp @@ -57,7 +57,7 @@ JSValue JSSVGPathSegList::initialize(ExecState* exec, const ArgList& args) SVGPathSeg* obj = WTF::getPtr(imp->initialize(newItem, ec)); - JSC::JSValue result = toJS(exec, obj, m_context.get()); + JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj, m_context.get()); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); @@ -78,7 +78,7 @@ JSValue JSSVGPathSegList::getItem(ExecState* exec, const ArgList& args) SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); SVGPathSeg* obj = WTF::getPtr(imp->getItem(index, ec)); - JSC::JSValue result = toJS(exec, obj, m_context.get()); + JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj, m_context.get()); setDOMException(exec, ec); return result; } @@ -97,7 +97,7 @@ JSValue JSSVGPathSegList::insertItemBefore(ExecState* exec, const ArgList& args) SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); - JSC::JSValue result = toJS(exec, WTF::getPtr(imp->insertItemBefore(newItem, index, ec)), m_context.get()); + JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->insertItemBefore(newItem, index, ec)), m_context.get()); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); @@ -118,7 +118,7 @@ JSValue JSSVGPathSegList::replaceItem(ExecState* exec, const ArgList& args) SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); - JSC::JSValue result = toJS(exec, WTF::getPtr(imp->replaceItem(newItem, index, ec)), m_context.get()); + JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->replaceItem(newItem, index, ec)), m_context.get()); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); @@ -140,7 +140,7 @@ JSValue JSSVGPathSegList::removeItem(ExecState* exec, const ArgList& args) RefPtr<SVGPathSeg> obj(imp->removeItem(index, ec)); - JSC::JSValue result = toJS(exec, obj.get(), m_context.get()); + JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj.get(), m_context.get()); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); @@ -154,7 +154,7 @@ JSValue JSSVGPathSegList::appendItem(ExecState* exec, const ArgList& args) SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); - JSC::JSValue result = toJS(exec, WTF::getPtr(imp->appendItem(newItem, ec)), m_context.get()); + JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->appendItem(newItem, ec)), m_context.get()); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); diff --git a/WebCore/bindings/js/JSSVGPointListCustom.cpp b/WebCore/bindings/js/JSSVGPointListCustom.cpp index a18c2a2..1969fe2 100644 --- a/WebCore/bindings/js/JSSVGPointListCustom.cpp +++ b/WebCore/bindings/js/JSSVGPointListCustom.cpp @@ -39,7 +39,7 @@ static JSValue finishGetter(ExecState* exec, ExceptionCode& ec, SVGElement* cont setDOMException(exec, ec); return jsUndefined(); } - return toJS(exec, JSSVGPODTypeWrapperCreatorForList<FloatPoint>::create(item.get(), list->associatedAttributeName()).get(), context); + return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<FloatPoint>::create(item.get(), list->associatedAttributeName()).get(), context); } static JSValue finishSetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGPointList* list, PassRefPtr<PODListItem > item) @@ -50,7 +50,7 @@ static JSValue finishSetter(ExecState* exec, ExceptionCode& ec, SVGElement* cont } const QualifiedName& attributeName = list->associatedAttributeName(); context->svgAttributeChanged(attributeName); - return toJS(exec, JSSVGPODTypeWrapperCreatorForList<FloatPoint>::create(item.get(), attributeName).get(), context); + return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<FloatPoint>::create(item.get(), attributeName).get(), context); } static JSValue finishSetterReadOnlyResult(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGPointList* list, PassRefPtr<PODListItem> item) @@ -60,7 +60,7 @@ static JSValue finishSetterReadOnlyResult(ExecState* exec, ExceptionCode& ec, SV return jsUndefined(); } context->svgAttributeChanged(list->associatedAttributeName()); - return toJS(exec, JSSVGStaticPODTypeWrapper<FloatPoint>::create(*item).get(), context); + return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<FloatPoint>::create(*item).get(), context); } JSValue JSSVGPointList::clear(ExecState* exec, const ArgList&) diff --git a/WebCore/bindings/js/JSSVGTransformListCustom.cpp b/WebCore/bindings/js/JSSVGTransformListCustom.cpp index 58b25ad..1a9110a 100644 --- a/WebCore/bindings/js/JSSVGTransformListCustom.cpp +++ b/WebCore/bindings/js/JSSVGTransformListCustom.cpp @@ -39,7 +39,7 @@ static JSValue finishGetter(ExecState* exec, ExceptionCode& ec, SVGElement* cont setDOMException(exec, ec); return jsUndefined(); } - return toJS(exec, JSSVGPODTypeWrapperCreatorForList<SVGTransform>::create(item.get(), list->associatedAttributeName()).get(), context); + return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<SVGTransform>::create(item.get(), list->associatedAttributeName()).get(), context); } static JSValue finishSetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGTransformList* list, PassRefPtr<PODListItem> item) @@ -50,7 +50,7 @@ static JSValue finishSetter(ExecState* exec, ExceptionCode& ec, SVGElement* cont } const QualifiedName& attributeName = list->associatedAttributeName(); context->svgAttributeChanged(attributeName); - return toJS(exec, JSSVGPODTypeWrapperCreatorForList<SVGTransform>::create(item.get(), attributeName).get(), context); + return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<SVGTransform>::create(item.get(), attributeName).get(), context); } static JSValue finishSetterReadOnlyResult(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGTransformList* list, PassRefPtr<PODListItem> item) @@ -60,7 +60,7 @@ static JSValue finishSetterReadOnlyResult(ExecState* exec, ExceptionCode& ec, SV return jsUndefined(); } context->svgAttributeChanged(list->associatedAttributeName()); - return toJS(exec, JSSVGStaticPODTypeWrapper<SVGTransform>::create(*item).get(), context); + return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<SVGTransform>::create(*item).get(), context); } JSValue JSSVGTransformList::clear(ExecState* exec, const ArgList&) diff --git a/WebCore/bindings/js/JSSharedWorkerConstructor.cpp b/WebCore/bindings/js/JSSharedWorkerConstructor.cpp new file mode 100644 index 0000000..e2f1136 --- /dev/null +++ b/WebCore/bindings/js/JSSharedWorkerConstructor.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(SHARED_WORKERS) + +#include "JSSharedWorkerConstructor.h" + +#include "JSDOMWindowCustom.h" +#include "JSSharedWorker.h" +#include "SharedWorker.h" + +using namespace JSC; + +namespace WebCore { + +const ClassInfo JSSharedWorkerConstructor::s_info = { "SharedWorkerConstructor", 0, 0, 0 }; + +JSSharedWorkerConstructor::JSSharedWorkerConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(JSSharedWorkerConstructor::createStructure(globalObject->objectPrototype()), globalObject) +{ + putDirect(exec->propertyNames().prototype, JSSharedWorkerPrototype::self(exec, globalObject), None); + // Host functions have a length property describing the number of expected arguments. + putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum); +} + +static JSObject* constructSharedWorker(ExecState* exec, JSObject* constructor, const ArgList& args) +{ + JSSharedWorkerConstructor* jsConstructor = static_cast<JSSharedWorkerConstructor*>(constructor); + + if (args.size() < 2) + return throwError(exec, SyntaxError, "Not enough arguments"); + + UString scriptURL = args.at(0).toString(exec); + UString name = args.at(1).toString(exec); + if (exec->hadException()) + return 0; + + // FIXME: We need to use both the dynamic scope and the lexical scope (dynamic scope for resolving the worker URL) + DOMWindow* window = asJSDOMWindow(exec->lexicalGlobalObject())->impl(); + ExceptionCode ec = 0; + RefPtr<SharedWorker> worker = SharedWorker::create(scriptURL, name, window->document(), ec); + setDOMException(exec, ec); + + return asObject(toJS(exec, jsConstructor->globalObject(), worker.release())); +} + +ConstructType JSSharedWorkerConstructor::getConstructData(ConstructData& constructData) +{ + constructData.native.function = constructSharedWorker; + return ConstructTypeHost; +} + + +} // namespace WebCore + +#endif // ENABLE(SHARED_WORKERS) diff --git a/WebCore/bindings/js/JSSharedWorkerConstructor.h b/WebCore/bindings/js/JSSharedWorkerConstructor.h new file mode 100644 index 0000000..87baa38 --- /dev/null +++ b/WebCore/bindings/js/JSSharedWorkerConstructor.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSSharedWorkerConstructor_h +#define JSSharedWorkerConstructor_h + +#if ENABLE(SHARED_WORKERS) + +#include "JSDOMBinding.h" + +namespace WebCore { + + class JSSharedWorkerConstructor : public DOMConstructorObject { + public: + JSSharedWorkerConstructor(JSC::ExecState*, JSDOMGlobalObject*); + + static const JSC::ClassInfo s_info; + + private: + virtual JSC::ConstructType getConstructData(JSC::ConstructData&); + + virtual const JSC::ClassInfo* classInfo() const { return &s_info; } + }; + +} // namespace WebCore + +#endif // ENABLE(SHARED_WORKERS) + +#endif // JSSharedWorkerConstructor_h diff --git a/WebCore/bindings/js/JSSharedWorkerContextCustom.cpp b/WebCore/bindings/js/JSSharedWorkerContextCustom.cpp new file mode 100644 index 0000000..dca3536 --- /dev/null +++ b/WebCore/bindings/js/JSSharedWorkerContextCustom.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(SHARED_WORKERS) + +#include "JSSharedWorkerContext.h" + +using namespace JSC; + +namespace WebCore { + +void JSSharedWorkerContext::markChildren(MarkStack& markStack) +{ + Base::markChildren(markStack); + + markIfNotNull(markStack, impl()->onconnect()); +} + +} // namespace WebCore + +#endif // ENABLE(SHARED_WORKERS) diff --git a/WebCore/bindings/js/JSSharedWorkerCustom.cpp b/WebCore/bindings/js/JSSharedWorkerCustom.cpp new file mode 100644 index 0000000..f21f50c --- /dev/null +++ b/WebCore/bindings/js/JSSharedWorkerCustom.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(SHARED_WORKERS) + +#include "JSSharedWorker.h" + +#include "JSDOMGlobalObject.h" +#include "SharedWorker.h" + +using namespace JSC; + +namespace WebCore { + +void JSSharedWorker::markChildren(MarkStack& markStack) +{ + Base::markChildren(markStack); + + if (MessagePort* port = impl()->port()) { + DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port); + if (wrapper) + markStack.append(wrapper); + } +} + +} // namespace WebCore + +#endif // ENABLE(SHARED_WORKERS) diff --git a/WebCore/bindings/js/JSStorageCustom.cpp b/WebCore/bindings/js/JSStorageCustom.cpp index bc43d79..07cf2f8 100644 --- a/WebCore/bindings/js/JSStorageCustom.cpp +++ b/WebCore/bindings/js/JSStorageCustom.cpp @@ -64,17 +64,16 @@ bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName) return true; } -bool JSStorage::customGetPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSStorage::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) { - ExceptionCode ec; unsigned length = m_impl->length(); for (unsigned i = 0; i < length; ++i) - propertyNames.add(Identifier(exec, m_impl->key(i, ec))); + propertyNames.add(Identifier(exec, m_impl->key(i))); - return false; + Base::getPropertyNames(exec, propertyNames); } -bool JSStorage::customPut(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&) +bool JSStorage::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&) { // Only perform the custom put if the object doesn't have a native property by this name. // Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check diff --git a/WebCore/bindings/js/JSStyleSheetCustom.cpp b/WebCore/bindings/js/JSStyleSheetCustom.cpp index f8146bd..43249dc 100644 --- a/WebCore/bindings/js/JSStyleSheetCustom.cpp +++ b/WebCore/bindings/js/JSStyleSheetCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,7 @@ using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, StyleSheet* styleSheet) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, StyleSheet* styleSheet) { if (!styleSheet) return jsNull(); @@ -45,16 +45,16 @@ JSValue toJS(ExecState* exec, StyleSheet* styleSheet) return wrapper; if (styleSheet->isCSSStyleSheet()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, CSSStyleSheet, styleSheet); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CSSStyleSheet, styleSheet); else - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, StyleSheet, styleSheet); + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, StyleSheet, styleSheet); return wrapper; } -void JSStyleSheet::mark() +void JSStyleSheet::markChildren(MarkStack& markStack) { - Base::mark(); + Base::markChildren(markStack); // This prevents us from having a style sheet with a dangling ownerNode pointer. // A better solution would be to handle this on the DOM side -- if the style sheet @@ -62,10 +62,8 @@ void JSStyleSheet::mark() // be to make ref/deref on the style sheet ref/deref the node instead, but there's // a lot of disentangling of the CSS DOM objects that would need to happen first. if (Node* ownerNode = impl()->ownerNode()) { - if (JSNode* ownerNodeWrapper = getCachedDOMNodeWrapper(ownerNode->document(), ownerNode)) { - if (!ownerNodeWrapper->marked()) - ownerNodeWrapper->mark(); - } + if (JSNode* ownerNodeWrapper = getCachedDOMNodeWrapper(ownerNode->document(), ownerNode)) + markStack.append(ownerNodeWrapper); } } diff --git a/WebCore/bindings/js/JSTextCustom.cpp b/WebCore/bindings/js/JSTextCustom.cpp index 9e66826..2dc886d 100644 --- a/WebCore/bindings/js/JSTextCustom.cpp +++ b/WebCore/bindings/js/JSTextCustom.cpp @@ -32,12 +32,12 @@ using namespace JSC; namespace WebCore { -JSValue toJSNewlyCreated(ExecState* exec, Text* text) +JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Text* text) { if (!text) return jsNull(); - return CREATE_DOM_NODE_WRAPPER(exec, Text, text); + return CREATE_DOM_NODE_WRAPPER(exec, globalObject, Text, text); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSTreeWalkerCustom.cpp b/WebCore/bindings/js/JSTreeWalkerCustom.cpp index 6369017..f879cf4 100644 --- a/WebCore/bindings/js/JSTreeWalkerCustom.cpp +++ b/WebCore/bindings/js/JSTreeWalkerCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,12 +29,12 @@ using namespace JSC; namespace WebCore { -void JSTreeWalker::mark() +void JSTreeWalker::markChildren(MarkStack& markStack) { + Base::markChildren(markStack); + if (NodeFilter* filter = m_impl->filter()) - filter->mark(); - - DOMObject::mark(); + filter->markAggregate(markStack); } JSValue JSTreeWalker::parentNode(ExecState* exec, const ArgList&) diff --git a/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.cpp b/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.cpp index c7fe4a5..bc05250 100644 --- a/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.cpp +++ b/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.cpp @@ -35,15 +35,16 @@ namespace WebCore { const ClassInfo JSWebKitCSSMatrixConstructor::s_info = { "WebKitCSSMatrixConstructor", 0, 0, 0 }; -JSWebKitCSSMatrixConstructor::JSWebKitCSSMatrixConstructor(ExecState* exec) - : DOMObject(JSWebKitCSSMatrixConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) +JSWebKitCSSMatrixConstructor::JSWebKitCSSMatrixConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(JSWebKitCSSMatrixConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - putDirect(exec->propertyNames().prototype, JSWebKitCSSMatrixPrototype::self(exec, exec->lexicalGlobalObject()), None); + putDirect(exec->propertyNames().prototype, JSWebKitCSSMatrixPrototype::self(exec, globalObject), None); putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly|DontDelete|DontEnum); } -static JSObject* constructWebKitCSSMatrix(ExecState* exec, JSObject*, const ArgList& args) +static JSObject* constructWebKitCSSMatrix(ExecState* exec, JSObject* constructor, const ArgList& args) { + JSWebKitCSSMatrixConstructor* jsConstructor = static_cast<JSWebKitCSSMatrixConstructor*>(constructor); String s; if (args.size() >= 1) s = args.at(0).toString(exec); @@ -51,7 +52,7 @@ static JSObject* constructWebKitCSSMatrix(ExecState* exec, JSObject*, const ArgL ExceptionCode ec = 0; RefPtr<WebKitCSSMatrix> matrix = WebKitCSSMatrix::create(s, ec); setDOMException(exec, ec); - return CREATE_DOM_OBJECT_WRAPPER(exec, WebKitCSSMatrix, matrix.get()); + return CREATE_DOM_OBJECT_WRAPPER(exec, jsConstructor->globalObject(), WebKitCSSMatrix, matrix.get()); } ConstructType JSWebKitCSSMatrixConstructor::getConstructData(ConstructData& constructData) diff --git a/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.h b/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.h index d0e0bd1..65b9050 100644 --- a/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.h +++ b/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.h @@ -31,9 +31,9 @@ namespace WebCore { -class JSWebKitCSSMatrixConstructor : public DOMObject { +class JSWebKitCSSMatrixConstructor : public DOMConstructorObject { public: - JSWebKitCSSMatrixConstructor(JSC::ExecState*); + JSWebKitCSSMatrixConstructor(JSC::ExecState*, JSDOMGlobalObject*); static const JSC::ClassInfo s_info; private: diff --git a/WebCore/bindings/js/JSWebKitPointConstructor.cpp b/WebCore/bindings/js/JSWebKitPointConstructor.cpp index c7d4e36..27cc1db 100644 --- a/WebCore/bindings/js/JSWebKitPointConstructor.cpp +++ b/WebCore/bindings/js/JSWebKitPointConstructor.cpp @@ -36,15 +36,17 @@ using namespace JSC; const ClassInfo JSWebKitPointConstructor::s_info = { "WebKitPointConstructor", 0, 0, 0 }; -JSWebKitPointConstructor::JSWebKitPointConstructor(ExecState* exec) - : DOMObject(JSWebKitPointConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) +JSWebKitPointConstructor::JSWebKitPointConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(JSWebKitPointConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - putDirect(exec->propertyNames().prototype, JSWebKitPointPrototype::self(exec, exec->lexicalGlobalObject()), None); + putDirect(exec->propertyNames().prototype, JSWebKitPointPrototype::self(exec, globalObject), None); putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum); } -static JSObject* constructWebKitPoint(ExecState* exec, JSObject*, const ArgList& args) +static JSObject* constructWebKitPoint(ExecState* exec, JSObject* constructor, const ArgList& args) { + JSWebKitPointConstructor* jsConstructor = static_cast<JSWebKitPointConstructor*>(constructor); + float x = 0; float y = 0; if (args.size() >= 2) { @@ -55,7 +57,7 @@ static JSObject* constructWebKitPoint(ExecState* exec, JSObject*, const ArgList& if (isnan(y)) y = 0; } - return asObject(toJS(exec, WebKitPoint::create(x, y))); + return asObject(toJS(exec, jsConstructor->globalObject(), WebKitPoint::create(x, y))); } JSC::ConstructType JSWebKitPointConstructor::getConstructData(JSC::ConstructData& constructData) diff --git a/WebCore/bindings/js/JSWebKitPointConstructor.h b/WebCore/bindings/js/JSWebKitPointConstructor.h index a5bb5c1..44c253d 100644 --- a/WebCore/bindings/js/JSWebKitPointConstructor.h +++ b/WebCore/bindings/js/JSWebKitPointConstructor.h @@ -31,9 +31,9 @@ namespace WebCore { -class JSWebKitPointConstructor : public DOMObject { +class JSWebKitPointConstructor : public DOMConstructorObject { public: - JSWebKitPointConstructor(JSC::ExecState*); + JSWebKitPointConstructor(JSC::ExecState*, JSDOMGlobalObject*); static const JSC::ClassInfo s_info; private: diff --git a/WebCore/bindings/js/JSWebSocketConstructor.cpp b/WebCore/bindings/js/JSWebSocketConstructor.cpp new file mode 100644 index 0000000..ca2e104 --- /dev/null +++ b/WebCore/bindings/js/JSWebSocketConstructor.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEB_SOCKETS) + +#include "JSWebSocketConstructor.h" + +#include "JSWebSocket.h" +#include "ScriptExecutionContext.h" +#include "WebSocket.h" + +using namespace JSC; + +namespace WebCore { + +ASSERT_CLASS_FITS_IN_CELL(JSWebSocketConstructor); + +const ClassInfo JSWebSocketConstructor::s_info = { "WebSocketConstructor", 0, 0, 0 }; + +JSWebSocketConstructor::JSWebSocketConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(JSWebSocketConstructor::createStructure(globalObject->objectPrototype()), globalObject) +{ + putDirect(exec->propertyNames().prototype, JSWebSocketPrototype::self(exec, globalObject), None); + putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum); +} + +static JSObject* constructWebSocket(ExecState* exec, JSObject* constructor, const ArgList& args) +{ + JSWebSocketConstructor* jsConstructor = static_cast<JSWebSocketConstructor*>(constructor); + ScriptExecutionContext* context = jsConstructor->scriptExecutionContext(); + if (!context) + return throwError(exec, ReferenceError, "WebSocket constructor associated document is unavailable"); + + if (args.size() == 0) + return throwError(exec, SyntaxError, "Not enough arguments"); + + const String& urlString = args.at(0).toString(exec); + if (exec->hadException()) + return throwError(exec, SyntaxError, "wrong URL"); + const KURL& url = context->completeURL(urlString); + RefPtr<WebSocket> webSocket = WebSocket::create(context); + ExceptionCode ec = 0; + if (args.size() < 2) + webSocket->connect(url, ec); + else { + const String& protocol = args.at(1).toString(exec); + if (exec->hadException()) + return 0; + webSocket->connect(url, protocol, ec); + } + setDOMException(exec, ec); + return CREATE_DOM_OBJECT_WRAPPER(exec, jsConstructor->globalObject(), WebSocket, webSocket.get()); +} + +ConstructType JSWebSocketConstructor::getConstructData(ConstructData& constructData) +{ + constructData.native.function = constructWebSocket; + return ConstructTypeHost; +} + +} // namespace WebCore + +#endif diff --git a/WebCore/bindings/js/JSWebSocketConstructor.h b/WebCore/bindings/js/JSWebSocketConstructor.h new file mode 100644 index 0000000..069647a --- /dev/null +++ b/WebCore/bindings/js/JSWebSocketConstructor.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSWebSocketConstructor_h +#define JSWebSocketConstructor_h + +#include "JSDOMBinding.h" + +namespace WebCore { + +class JSWebSocketConstructor : public DOMConstructorObject { + public: + JSWebSocketConstructor(JSC::ExecState*, JSDOMGlobalObject*); + static const JSC::ClassInfo s_info; + + private: + virtual JSC::ConstructType getConstructData(JSC::ConstructData&); + virtual const JSC::ClassInfo* classInfo() const { return &s_info; } +}; + +} // namespace WebCore + +#endif // JSWebSocketConstructor_h diff --git a/WebCore/bindings/js/JSWebSocketCustom.cpp b/WebCore/bindings/js/JSWebSocketCustom.cpp new file mode 100644 index 0000000..3aa4b8b --- /dev/null +++ b/WebCore/bindings/js/JSWebSocketCustom.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009 Apple, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEB_SOCKETS) + +#include "JSWebSocket.h" + +#include "KURL.h" +#include "WebSocket.h" +#include "NotImplemented.h" + +using namespace JSC; + +namespace WebCore { + +void JSWebSocket::markChildren(MarkStack& markStack) +{ + Base::markChildren(markStack); + if (m_impl->readyState() != WebSocket::CLOSED) + markIfNotNull(markStack, m_impl->onmessage()); + // FIXME: mark if EventListeners is registered. +} + +// Custom functions +JSValue JSWebSocket::send(ExecState* exec, const ArgList& args) +{ + if (args.size() < 1) + return throwError(exec, SyntaxError, "Not enough arguments"); + + const String& msg = args.at(0).toString(exec); + if (exec->hadException()) + return throwError(exec, SyntaxError, "bad message data."); + ExceptionCode ec = 0; + JSValue ret = jsBoolean(impl()->send(msg, ec)); + setDOMException(exec, ec); + return ret; +} + +// FIXME: implement addEventListener/removeEventListener. + +} // namespace WebCore + +#endif diff --git a/WebCore/bindings/js/JSWorkerConstructor.cpp b/WebCore/bindings/js/JSWorkerConstructor.cpp index 8ea6718..9943cfb 100644 --- a/WebCore/bindings/js/JSWorkerConstructor.cpp +++ b/WebCore/bindings/js/JSWorkerConstructor.cpp @@ -41,15 +41,17 @@ namespace WebCore { const ClassInfo JSWorkerConstructor::s_info = { "WorkerConstructor", 0, 0, 0 }; -JSWorkerConstructor::JSWorkerConstructor(ExecState* exec) - : DOMObject(JSWorkerConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) +JSWorkerConstructor::JSWorkerConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(JSWorkerConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - putDirect(exec->propertyNames().prototype, JSWorkerPrototype::self(exec, exec->lexicalGlobalObject()), None); + putDirect(exec->propertyNames().prototype, JSWorkerPrototype::self(exec, globalObject), None); putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly|DontDelete|DontEnum); } -static JSObject* constructWorker(ExecState* exec, JSObject*, const ArgList& args) +static JSObject* constructWorker(ExecState* exec, JSObject* constructor, const ArgList& args) { + JSWorkerConstructor* jsConstructor = static_cast<JSWorkerConstructor*>(constructor); + if (args.size() == 0) return throwError(exec, SyntaxError, "Not enough arguments"); @@ -57,13 +59,17 @@ static JSObject* constructWorker(ExecState* exec, JSObject*, const ArgList& args if (exec->hadException()) return 0; + // See section 4.8.2 step 14 of WebWorkers for why this is the lexicalGlobalObject. DOMWindow* window = asJSDOMWindow(exec->lexicalGlobalObject())->impl(); - + ExceptionCode ec = 0; RefPtr<Worker> worker = Worker::create(scriptURL, window->document(), ec); - setDOMException(exec, ec); + if (ec) { + setDOMException(exec, ec); + return 0; + } - return asObject(toJS(exec, worker.release())); + return asObject(toJS(exec, jsConstructor->globalObject(), worker.release())); } ConstructType JSWorkerConstructor::getConstructData(ConstructData& constructData) diff --git a/WebCore/bindings/js/JSWorkerConstructor.h b/WebCore/bindings/js/JSWorkerConstructor.h index d1df7eb..c845fa6 100644 --- a/WebCore/bindings/js/JSWorkerConstructor.h +++ b/WebCore/bindings/js/JSWorkerConstructor.h @@ -32,9 +32,9 @@ namespace WebCore { - class JSWorkerConstructor : public DOMObject { + class JSWorkerConstructor : public DOMConstructorObject { public: - JSWorkerConstructor(JSC::ExecState*); + JSWorkerConstructor(JSC::ExecState*, JSDOMGlobalObject*); static const JSC::ClassInfo s_info; diff --git a/WebCore/bindings/js/JSWorkerContextBase.cpp b/WebCore/bindings/js/JSWorkerContextBase.cpp index c71f45b..1e4df42 100644 --- a/WebCore/bindings/js/JSWorkerContextBase.cpp +++ b/WebCore/bindings/js/JSWorkerContextBase.cpp @@ -31,6 +31,8 @@ #include "JSWorkerContextBase.h" +#include "JSDedicatedWorkerContext.h" +#include "JSSharedWorkerContext.h" #include "JSWorkerContext.h" #include "WorkerContext.h" @@ -57,6 +59,11 @@ ScriptExecutionContext* JSWorkerContextBase::scriptExecutionContext() const return m_impl.get(); } +JSValue toJS(ExecState* exec, JSDOMGlobalObject*, WorkerContext* workerContext) +{ + return toJS(exec, workerContext); +} + JSValue toJS(ExecState*, WorkerContext* workerContext) { if (!workerContext) @@ -67,6 +74,38 @@ JSValue toJS(ExecState*, WorkerContext* workerContext) return script->workerContextWrapper(); } +JSDedicatedWorkerContext* toJSDedicatedWorkerContext(JSValue value) +{ + if (!value.isObject()) + return 0; + const ClassInfo* classInfo = asObject(value)->classInfo(); + if (classInfo == &JSDedicatedWorkerContext::s_info) + return static_cast<JSDedicatedWorkerContext*>(asObject(value)); + return 0; +} + +#if ENABLE(SHARED_WORKERS) +JSSharedWorkerContext* toJSSharedWorkerContext(JSValue value) +{ + if (!value.isObject()) + return 0; + const ClassInfo* classInfo = asObject(value)->classInfo(); + if (classInfo == &JSSharedWorkerContext::s_info) + return static_cast<JSSharedWorkerContext*>(asObject(value)); + return 0; +} +#endif + +JSWorkerContext* toJSWorkerContext(JSValue value) +{ + JSWorkerContext* context = toJSDedicatedWorkerContext(value); +#if ENABLE(SHARED_WORKERS) + if (!context) + context = toJSSharedWorkerContext(value); +#endif + return context; +} + } // namespace WebCore #endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/js/JSWorkerContextBase.h b/WebCore/bindings/js/JSWorkerContextBase.h index dcbc5c3..a9a6e63 100644 --- a/WebCore/bindings/js/JSWorkerContextBase.h +++ b/WebCore/bindings/js/JSWorkerContextBase.h @@ -33,6 +33,9 @@ namespace WebCore { + class JSDedicatedWorkerContext; + class JSSharedWorkerContext; + class JSWorkerContext; class WorkerContext; class JSWorkerContextBase : public JSDOMGlobalObject { @@ -52,8 +55,17 @@ namespace WebCore { }; // Returns a JSWorkerContext or jsNull() + // Always ignores the execState and passed globalObject, WorkerContext is itself a globalObject and will always use its own prototype chain. + JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, WorkerContext*); JSC::JSValue toJS(JSC::ExecState*, WorkerContext*); + JSDedicatedWorkerContext* toJSDedicatedWorkerContext(JSC::JSValue); + JSWorkerContext* toJSWorkerContext(JSC::JSValue); + +#if ENABLE(SHARED_WORKERS) + JSSharedWorkerContext* toJSSharedWorkerContext(JSC::JSValue); +#endif + } // namespace WebCore #endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/js/JSWorkerContextCustom.cpp b/WebCore/bindings/js/JSWorkerContextCustom.cpp index 6824914..919c81f 100644 --- a/WebCore/bindings/js/JSWorkerContextCustom.cpp +++ b/WebCore/bindings/js/JSWorkerContextCustom.cpp @@ -30,7 +30,10 @@ #include "JSWorkerContext.h" #include "JSDOMBinding.h" +#include "JSDOMGlobalObject.h" #include "JSEventListener.h" +#include "JSMessageChannelConstructor.h" +#include "JSMessagePort.h" #include "JSWorkerLocation.h" #include "JSWorkerNavigator.h" #include "JSXMLHttpRequestConstructor.h" @@ -44,29 +47,29 @@ using namespace JSC; namespace WebCore { -void JSWorkerContext::mark() +void JSWorkerContext::markChildren(MarkStack& markStack) { - Base::mark(); + Base::markChildren(markStack); JSGlobalData& globalData = *this->globalData(); - markActiveObjectsForContext(globalData, scriptExecutionContext()); + markActiveObjectsForContext(markStack, globalData, scriptExecutionContext()); - markDOMObjectWrapper(globalData, impl()->optionalLocation()); - markDOMObjectWrapper(globalData, impl()->optionalNavigator()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator()); - markIfNotNull(impl()->onmessage()); + markIfNotNull(markStack, impl()->onerror()); typedef WorkerContext::EventListenersMap EventListenersMap; typedef WorkerContext::ListenerVector ListenerVector; EventListenersMap& eventListeners = impl()->eventListeners(); for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) { for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) - (*vecIter)->markJSFunction(); + (*vecIter)->markJSFunction(markStack); } } -bool JSWorkerContext::customGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +bool JSWorkerContext::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { // Look for overrides before looking at any of our own properties. if (JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot)) @@ -138,6 +141,14 @@ JSValue JSWorkerContext::setInterval(ExecState* exec, const ArgList& args) return jsNumber(exec, impl()->setInterval(action, delay)); } + +#if ENABLE(CHANNEL_MESSAGING) +JSValue JSWorkerContext::messageChannel(ExecState* exec) const +{ + return getDOMConstructor<JSMessageChannelConstructor>(exec, this); +} +#endif + } // namespace WebCore #endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/js/JSWorkerCustom.cpp b/WebCore/bindings/js/JSWorkerCustom.cpp index f4d3033..f5c394b 100644 --- a/WebCore/bindings/js/JSWorkerCustom.cpp +++ b/WebCore/bindings/js/JSWorkerCustom.cpp @@ -30,51 +30,17 @@ #include "JSWorker.h" #include "JSDOMGlobalObject.h" -#include "JSEventListener.h" #include "Worker.h" using namespace JSC; namespace WebCore { -void JSWorker::mark() +void JSWorker::markChildren(MarkStack& markStack) { - DOMObject::mark(); + Base::markChildren(markStack); - markIfNotNull(m_impl->onmessage()); - markIfNotNull(m_impl->onerror()); - - typedef Worker::EventListenersMap EventListenersMap; - typedef Worker::ListenerVector ListenerVector; - EventListenersMap& eventListeners = m_impl->eventListeners(); - for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) { - for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) - (*vecIter)->markJSFunction(); - } -} - -JSValue JSWorker::addEventListener(ExecState* exec, const ArgList& args) -{ - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext()); - if (!globalObject) - return jsUndefined(); - RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1)); - if (!listener) - return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSWorker::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext()); - if (!globalObject) - return jsUndefined(); - JSEventListener* listener = globalObject->findJSEventListener(args.at(1)); - if (!listener) - return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec)); - return jsUndefined(); + markIfNotNull(markStack, static_cast<Worker*>(impl())->onmessage()); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp b/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp index 65cdfc2..a644c9e 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp @@ -33,25 +33,20 @@ ASSERT_CLASS_FITS_IN_CELL(JSXMLHttpRequestConstructor); const ClassInfo JSXMLHttpRequestConstructor::s_info = { "XMLHttpRequestConstructor", 0, 0, 0 }; JSXMLHttpRequestConstructor::JSXMLHttpRequestConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMObject(JSXMLHttpRequestConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) - , m_globalObject(globalObject) + : DOMConstructorObject(JSXMLHttpRequestConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - putDirect(exec->propertyNames().prototype, JSXMLHttpRequestPrototype::self(exec, exec->lexicalGlobalObject()), None); -} - -ScriptExecutionContext* JSXMLHttpRequestConstructor::scriptExecutionContext() const -{ - return m_globalObject->scriptExecutionContext(); + putDirect(exec->propertyNames().prototype, JSXMLHttpRequestPrototype::self(exec, globalObject), None); } static JSObject* constructXMLHttpRequest(ExecState* exec, JSObject* constructor, const ArgList&) { - ScriptExecutionContext* context = static_cast<JSXMLHttpRequestConstructor*>(constructor)->scriptExecutionContext(); + JSXMLHttpRequestConstructor* jsConstructor = static_cast<JSXMLHttpRequestConstructor*>(constructor); + ScriptExecutionContext* context = jsConstructor->scriptExecutionContext(); if (!context) return throwError(exec, ReferenceError, "XMLHttpRequest constructor associated document is unavailable"); RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context); - return CREATE_DOM_OBJECT_WRAPPER(exec, XMLHttpRequest, xmlHttpRequest.get()); + return CREATE_DOM_OBJECT_WRAPPER(exec, jsConstructor->globalObject(), XMLHttpRequest, xmlHttpRequest.get()); } ConstructType JSXMLHttpRequestConstructor::getConstructData(ConstructData& constructData) @@ -60,11 +55,4 @@ ConstructType JSXMLHttpRequestConstructor::getConstructData(ConstructData& const return ConstructTypeHost; } -void JSXMLHttpRequestConstructor::mark() -{ - DOMObject::mark(); - if (!m_globalObject->marked()) - m_globalObject->mark(); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSXMLHttpRequestConstructor.h b/WebCore/bindings/js/JSXMLHttpRequestConstructor.h index 978a9f0..2cc4fcf 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestConstructor.h +++ b/WebCore/bindings/js/JSXMLHttpRequestConstructor.h @@ -24,18 +24,13 @@ namespace WebCore { -class JSXMLHttpRequestConstructor : public DOMObject { +class JSXMLHttpRequestConstructor : public DOMConstructorObject { public: JSXMLHttpRequestConstructor(JSC::ExecState*, JSDOMGlobalObject*); - ScriptExecutionContext* scriptExecutionContext() const; static const JSC::ClassInfo s_info; - - virtual void mark(); private: virtual JSC::ConstructType getConstructData(JSC::ConstructData&); virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - - JSDOMGlobalObject* m_globalObject; }; } // namespace WebCore diff --git a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp index 06a5817..a591fae 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp @@ -49,29 +49,29 @@ using namespace JSC; namespace WebCore { -void JSXMLHttpRequest::mark() +void JSXMLHttpRequest::markChildren(MarkStack& markStack) { - Base::mark(); + Base::markChildren(markStack); if (XMLHttpRequestUpload* upload = m_impl->optionalUpload()) { DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), upload); - if (wrapper && !wrapper->marked()) - wrapper->mark(); + if (wrapper) + markStack.append(wrapper); } - markIfNotNull(m_impl->onreadystatechange()); - markIfNotNull(m_impl->onabort()); - markIfNotNull(m_impl->onerror()); - markIfNotNull(m_impl->onload()); - markIfNotNull(m_impl->onloadstart()); - markIfNotNull(m_impl->onprogress()); + markIfNotNull(markStack, m_impl->onreadystatechange()); + markIfNotNull(markStack, m_impl->onabort()); + markIfNotNull(markStack, m_impl->onerror()); + markIfNotNull(markStack, m_impl->onload()); + markIfNotNull(markStack, m_impl->onloadstart()); + markIfNotNull(markStack, m_impl->onprogress()); typedef XMLHttpRequest::EventListenersMap EventListenersMap; typedef XMLHttpRequest::ListenerVector ListenerVector; EventListenersMap& eventListeners = m_impl->eventListeners(); for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) { for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) - (*vecIter)->markJSFunction(); + (*vecIter)->markJSFunction(markStack); } } diff --git a/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp index 597010c..cb6d5f2 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp @@ -41,28 +41,28 @@ using namespace JSC; namespace WebCore { -void JSXMLHttpRequestUpload::mark() +void JSXMLHttpRequestUpload::markChildren(MarkStack& markStack) { - Base::mark(); + Base::markChildren(markStack); if (XMLHttpRequest* xmlHttpRequest = m_impl->associatedXMLHttpRequest()) { DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), xmlHttpRequest); - if (wrapper && !wrapper->marked()) - wrapper->mark(); + if (wrapper) + markStack.append(wrapper); } - markIfNotNull(m_impl->onabort()); - markIfNotNull(m_impl->onerror()); - markIfNotNull(m_impl->onload()); - markIfNotNull(m_impl->onloadstart()); - markIfNotNull(m_impl->onprogress()); + markIfNotNull(markStack, m_impl->onabort()); + markIfNotNull(markStack, m_impl->onerror()); + markIfNotNull(markStack, m_impl->onload()); + markIfNotNull(markStack, m_impl->onloadstart()); + markIfNotNull(markStack, m_impl->onprogress()); typedef XMLHttpRequestUpload::EventListenersMap EventListenersMap; typedef XMLHttpRequestUpload::ListenerVector ListenerVector; EventListenersMap& eventListeners = m_impl->eventListeners(); for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) { for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) - (*vecIter)->markJSFunction(); + (*vecIter)->markJSFunction(markStack); } } diff --git a/WebCore/bindings/js/JSXSLTProcessorConstructor.cpp b/WebCore/bindings/js/JSXSLTProcessorConstructor.cpp index 807b017..07fec72 100644 --- a/WebCore/bindings/js/JSXSLTProcessorConstructor.cpp +++ b/WebCore/bindings/js/JSXSLTProcessorConstructor.cpp @@ -41,15 +41,16 @@ ASSERT_CLASS_FITS_IN_CELL(JSXSLTProcessorConstructor); const ClassInfo JSXSLTProcessorConstructor::s_info = { "XSLTProcessorConsructor", 0, 0, 0 }; -JSXSLTProcessorConstructor::JSXSLTProcessorConstructor(ExecState* exec) - : DOMObject(JSXSLTProcessorConstructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) +JSXSLTProcessorConstructor::JSXSLTProcessorConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(JSXSLTProcessorConstructor::createStructure(globalObject->objectPrototype()), globalObject) { - putDirect(exec->propertyNames().prototype, JSXSLTProcessorPrototype::self(exec, exec->lexicalGlobalObject()), None); + putDirect(exec->propertyNames().prototype, JSXSLTProcessorPrototype::self(exec, globalObject), None); } -static JSObject* constructXSLTProcessor(ExecState* exec, JSObject*, const ArgList&) +static JSObject* constructXSLTProcessor(ExecState* exec, JSObject* constructor, const ArgList&) { - return CREATE_DOM_OBJECT_WRAPPER(exec, XSLTProcessor, XSLTProcessor::create().get()); + JSXSLTProcessorConstructor* jsConstructor = static_cast<JSXSLTProcessorConstructor*>(constructor); + return CREATE_DOM_OBJECT_WRAPPER(exec, jsConstructor->globalObject(), XSLTProcessor, XSLTProcessor::create().get()); } ConstructType JSXSLTProcessorConstructor::getConstructData(ConstructData& constructData) diff --git a/WebCore/bindings/js/JSXSLTProcessorConstructor.h b/WebCore/bindings/js/JSXSLTProcessorConstructor.h index 64ef944..96fa607 100644 --- a/WebCore/bindings/js/JSXSLTProcessorConstructor.h +++ b/WebCore/bindings/js/JSXSLTProcessorConstructor.h @@ -32,9 +32,9 @@ namespace WebCore { - class JSXSLTProcessorConstructor : public DOMObject { + class JSXSLTProcessorConstructor : public DOMConstructorObject { public: - JSXSLTProcessorConstructor(JSC::ExecState*); + JSXSLTProcessorConstructor(JSC::ExecState*, JSDOMGlobalObject*); static const JSC::ClassInfo s_info; private: diff --git a/WebCore/bindings/js/ScheduledAction.cpp b/WebCore/bindings/js/ScheduledAction.cpp index 91bece7..9e64bce 100644 --- a/WebCore/bindings/js/ScheduledAction.cpp +++ b/WebCore/bindings/js/ScheduledAction.cpp @@ -87,7 +87,7 @@ void ScheduledAction::execute(ScriptExecutionContext* context) void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue) { ASSERT(m_function); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); CallData callData; CallType callType = m_function.get().getCallData(callData); diff --git a/WebCore/bindings/js/ScriptArray.cpp b/WebCore/bindings/js/ScriptArray.cpp new file mode 100644 index 0000000..2c4075a --- /dev/null +++ b/WebCore/bindings/js/ScriptArray.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScriptArray.h" + +#include <runtime/JSLock.h> + +using namespace JSC; + +namespace WebCore { + +ScriptArray::ScriptArray(ScriptState* scriptState, JSArray* object) + : ScriptObject(scriptState, object) +{ +} + +static bool handleException(ScriptState* scriptState) +{ + if (!scriptState->hadException()) + return true; + + reportException(scriptState, scriptState->exception()); + return false; +} + +bool ScriptArray::set(unsigned index, const ScriptObject& value) +{ + JSLock lock(SilenceAssertionsOnly); + jsArray()->put(m_scriptState, index, value.jsObject()); + return handleException(m_scriptState); +} + +bool ScriptArray::set(unsigned index, const String& value) +{ + JSLock lock(SilenceAssertionsOnly); + jsArray()->put(m_scriptState, index, jsString(m_scriptState, value)); + return handleException(m_scriptState); +} + +bool ScriptArray::set(unsigned index, double value) +{ + JSLock lock(SilenceAssertionsOnly); + jsArray()->put(m_scriptState, index, jsNumber(m_scriptState, value)); + return handleException(m_scriptState); +} + +bool ScriptArray::set(unsigned index, long long value) +{ + JSLock lock(SilenceAssertionsOnly); + jsArray()->put(m_scriptState, index, jsNumber(m_scriptState, value)); + return handleException(m_scriptState); +} + +bool ScriptArray::set(unsigned index, int value) +{ + JSLock lock(SilenceAssertionsOnly); + jsArray()->put(m_scriptState, index, jsNumber(m_scriptState, value)); + return handleException(m_scriptState); +} + +bool ScriptArray::set(unsigned index, bool value) +{ + JSLock lock(SilenceAssertionsOnly); + jsArray()->put(m_scriptState, index, jsBoolean(value)); + return handleException(m_scriptState); +} + +unsigned ScriptArray::length() +{ + JSLock lock(SilenceAssertionsOnly); + return jsArray()->length(); +} + +ScriptArray ScriptArray::createNew(ScriptState* scriptState) +{ + JSLock lock(SilenceAssertionsOnly); + return ScriptArray(scriptState, constructEmptyArray(scriptState)); +} + +} // namespace WebCore diff --git a/WebCore/bindings/js/ScriptArray.h b/WebCore/bindings/js/ScriptArray.h new file mode 100644 index 0000000..9240368 --- /dev/null +++ b/WebCore/bindings/js/ScriptArray.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScriptArray_h +#define ScriptArray_h + +#include "ScriptObject.h" +#include "ScriptState.h" + +#include <runtime/JSArray.h> + +namespace WebCore { + + class ScriptArray : public ScriptObject { + public: + ScriptArray(ScriptState*, JSC::JSArray*); + ScriptArray() {} + JSC::JSArray* jsArray() const { return asArray(jsValue()); } + + bool set(unsigned index, const ScriptObject&); + bool set(unsigned index, const String&); + bool set(unsigned index, double); + bool set(unsigned index, long long); + bool set(unsigned index, int); + bool set(unsigned index, bool); + unsigned length(); + + static ScriptArray createNew(ScriptState*); + }; +} + +#endif // ScriptArray_h diff --git a/WebCore/bindings/js/ScriptCachedFrameData.cpp b/WebCore/bindings/js/ScriptCachedFrameData.cpp index 213c708..8852611 100644 --- a/WebCore/bindings/js/ScriptCachedFrameData.cpp +++ b/WebCore/bindings/js/ScriptCachedFrameData.cpp @@ -45,7 +45,7 @@ namespace WebCore { ScriptCachedFrameData::ScriptCachedFrameData(Frame* frame) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); ScriptController* scriptController = frame->script(); if (scriptController->haveWindowShell()) { @@ -67,7 +67,7 @@ void ScriptCachedFrameData::restore(Frame* frame) { Page* page = frame->page(); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); ScriptController* scriptController = frame->script(); if (scriptController->haveWindowShell()) { @@ -84,7 +84,7 @@ void ScriptCachedFrameData::restore(Frame* frame) void ScriptCachedFrameData::clear() { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); if (!m_window) { m_window = 0; diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index 2f676c0..8908155 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -33,6 +33,7 @@ #include "ScriptSourceCode.h" #include "ScriptValue.h" #include "Settings.h" +#include "XSSAuditor.h" #include "npruntime_impl.h" #include "runtime_root.h" #include <debugger/Debugger.h> @@ -55,6 +56,7 @@ ScriptController::ScriptController(Frame* frame) #if PLATFORM(MAC) , m_windowScriptObject(0) #endif + , m_XSSAuditor(new XSSAuditor(frame)) { #if PLATFORM(MAC) && ENABLE(MAC_JAVA_BRIDGE) static bool initializedJavaJSBindings; @@ -79,10 +81,21 @@ ScriptController::~ScriptController() ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { + const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); + String sourceURL = jsSourceCode.provider()->url(); + + if (sourceURL.isNull() && !m_XSSAuditor->canEvaluateJavaScriptURL(sourceCode.source())) { + // This JavaScript URL is not safe to be evaluated. + return JSValue(); + } + + if (!sourceURL.isNull() && !m_XSSAuditor->canEvaluate(sourceCode.source())) { + // This script is not safe to be evaluated. + return JSValue(); + } + // evaluate code. Returns the JS return value or 0 // if there was none, an error occured or the type couldn't be converted. - - const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); initScriptIfNeeded(); // inlineCode is true for <a href="javascript:doSomething()"> @@ -91,10 +104,9 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) // See smart window.open policy for where this is used. ExecState* exec = m_windowShell->window()->globalExec(); const String* savedSourceURL = m_sourceURL; - String sourceURL = jsSourceCode.provider()->url(); m_sourceURL = &sourceURL; - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); RefPtr<Frame> protect = m_frame; @@ -123,7 +135,7 @@ void ScriptController::clearWindowShell() if (!m_windowShell) return; - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); // Clear the debugger from the current window before setting the new window. attachDebugger(0); @@ -145,7 +157,7 @@ void ScriptController::initScript() if (m_windowShell) return; - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); m_windowShell = new JSDOMWindowShell(m_frame->domWindow()); m_windowShell->window()->updateDocument(); @@ -242,7 +254,7 @@ void ScriptController::updateDocument() if (!m_frame->document()) return; - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); if (m_windowShell) m_windowShell->window()->updateDocument(); } @@ -258,7 +270,7 @@ Bindings::RootObject* ScriptController::bindingRootObject() return 0; if (!m_bindingRootObject) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); m_bindingRootObject = Bindings::RootObject::create(0, globalObject()); } return m_bindingRootObject.get(); @@ -284,7 +296,7 @@ NPObject* ScriptController::windowScriptNPObject() if (isEnabled()) { // JavaScript is enabled, so there is a JavaScript window object. // Return an NPObject bound to the window object. - JSC::JSLock lock(false); + JSC::JSLock lock(SilenceAssertionsOnly); JSObject* win = windowShell()->window(); ASSERT(win); Bindings::RootObject* root = bindingRootObject(); @@ -318,9 +330,9 @@ JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin) return 0; // Create a JSObject bound to this element - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); ExecState* exec = globalObject()->globalExec(); - JSValue jsElementValue = toJS(exec, plugin); + JSValue jsElementValue = toJS(exec, globalObject(), plugin); if (!jsElementValue || !jsElementValue.isObject()) return 0; @@ -352,7 +364,7 @@ void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) void ScriptController::clearScriptObjects() { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); RootObjectMap::const_iterator end = m_rootObjects.end(); for (RootObjectMap::const_iterator it = m_rootObjects.begin(); it != end; ++it) diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index f700cd9..4528495 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -58,6 +58,7 @@ class ScriptSourceCode; class ScriptValue; class String; class Widget; +class XSSAuditor; typedef HashMap<void*, RefPtr<JSC::Bindings::RootObject> > RootObjectMap; @@ -132,6 +133,8 @@ public: NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*); NPObject* windowScriptNPObject(); #endif + + XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); } private: void initScriptIfNeeded() @@ -164,6 +167,9 @@ private: #if PLATFORM(MAC) RetainPtr<WebScriptObject> m_windowScriptObject; #endif + + // The XSSAuditor associated with this ScriptController. + OwnPtr<XSSAuditor> m_XSSAuditor; }; } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptControllerHaiku.cpp b/WebCore/bindings/js/ScriptControllerHaiku.cpp new file mode 100644 index 0000000..b573b97 --- /dev/null +++ b/WebCore/bindings/js/ScriptControllerHaiku.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008 Apple Computer, Inc. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScriptController.h" + +#include "PluginView.h" +#include "runtime_root.h" +#include "runtime.h" + + +namespace WebCore { + +PassRefPtr<JSC::Bindings::Instance> ScriptController::createScriptInstanceForWidget(Widget* widget) +{ + if (!widget->isPluginView()) + return 0; + + return static_cast<PluginView*>(widget)->bindingInstance(); +} + +} // namespace WebCore + diff --git a/WebCore/bindings/js/ScriptControllerMac.mm b/WebCore/bindings/js/ScriptControllerMac.mm index 502a504..e6a654f 100644 --- a/WebCore/bindings/js/ScriptControllerMac.mm +++ b/WebCore/bindings/js/ScriptControllerMac.mm @@ -112,7 +112,7 @@ WebScriptObject* ScriptController::windowScriptObject() return 0; if (!m_windowScriptObject) { - JSC::JSLock lock(false); + JSC::JSLock lock(JSC::SilenceAssertionsOnly); JSC::Bindings::RootObject* root = bindingRootObject(); m_windowScriptObject = [WebScriptObject scriptObjectForJSObject:toRef(windowShell()) originRootObject:root rootObject:root]; } diff --git a/WebCore/bindings/js/ScriptEventListener.cpp b/WebCore/bindings/js/ScriptEventListener.cpp index 0ce7bca..878c535 100644 --- a/WebCore/bindings/js/ScriptEventListener.cpp +++ b/WebCore/bindings/js/ScriptEventListener.cpp @@ -35,6 +35,7 @@ #include "Document.h" #include "JSNode.h" #include "Frame.h" +#include "XSSAuditor.h" #include <runtime/JSLock.h> @@ -61,12 +62,18 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribu if (!scriptController->isEnabled()) return 0; + if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { + // This script is not safe to execute. + return 0; + } + JSDOMWindow* globalObject = scriptController->globalObject(); // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating. { - JSLock lock(false); - toJS(globalObject->globalExec(), node); + JSLock lock(SilenceAssertionsOnly); + // FIXME: Should pass the global object associated with the node + toJS(globalObject->globalExec(), globalObject, node); } return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), globalObject, node, scriptController->eventHandlerLineNumber()); @@ -80,6 +87,11 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attri ScriptController* scriptController = frame->script(); if (!scriptController->isEnabled()) return 0; + + if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { + // This script is not safe to execute. + return 0; + } // 'globalObject' is the JavaScript wrapper that will mark the event listener we're creating. JSDOMWindow* globalObject = scriptController->globalObject(); diff --git a/WebCore/bindings/js/ScriptFunctionCall.cpp b/WebCore/bindings/js/ScriptFunctionCall.cpp index 1122931..46e80ac 100644 --- a/WebCore/bindings/js/ScriptFunctionCall.cpp +++ b/WebCore/bindings/js/ScriptFunctionCall.cpp @@ -66,7 +66,7 @@ void ScriptFunctionCall::appendArgument(const ScriptValue& argument) void ScriptFunctionCall::appendArgument(const String& argument) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); m_arguments.append(jsString(m_exec, argument)); } @@ -82,19 +82,19 @@ void ScriptFunctionCall::appendArgument(JSC::JSValue argument) void ScriptFunctionCall::appendArgument(long long argument) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); m_arguments.append(jsNumber(m_exec, argument)); } void ScriptFunctionCall::appendArgument(unsigned int argument) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); m_arguments.append(jsNumber(m_exec, argument)); } void ScriptFunctionCall::appendArgument(int argument) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); m_arguments.append(jsNumber(m_exec, argument)); } @@ -107,7 +107,7 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) { JSObject* thisObject = m_thisObject.jsObject(); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSValue function = thisObject->get(m_exec, Identifier(m_exec, m_name)); if (m_exec->hadException()) { @@ -145,7 +145,7 @@ ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExcept { JSObject* thisObject = m_thisObject.jsObject(); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSObject* constructor = asObject(thisObject->get(m_exec, Identifier(m_exec, m_name))); if (m_exec->hadException()) { @@ -170,7 +170,7 @@ ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExcept return ScriptObject(); } - return ScriptObject(asObject(result)); + return ScriptObject(m_exec, asObject(result)); } } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptObject.cpp b/WebCore/bindings/js/ScriptObject.cpp index 44337bd..c5fa399 100644 --- a/WebCore/bindings/js/ScriptObject.cpp +++ b/WebCore/bindings/js/ScriptObject.cpp @@ -32,10 +32,14 @@ #include "ScriptObject.h" #include "JSDOMBinding.h" +#ifdef MANUAL_MERGE_REQUIRED #if ENABLE(JAVASCRIPT_DEBUGGER) #include "JSInspectorController.h" #endif +#else // MANUAL_MERGE_REQUIRED +#include "JSInspectorBackend.h" +#endif // MANUAL_MERGE_REQUIRED #include <runtime/JSLock.h> @@ -43,8 +47,9 @@ using namespace JSC; namespace WebCore { -ScriptObject::ScriptObject(JSObject* object) +ScriptObject::ScriptObject(ScriptState* scriptState, JSObject* object) : ScriptValue(object) + , m_scriptState(scriptState) { } @@ -57,87 +62,92 @@ static bool handleException(ScriptState* scriptState) return false; } -bool ScriptObject::set(ScriptState* scriptState, const String& name, const String& value) +bool ScriptObject::set(const String& name, const String& value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - jsObject()->put(scriptState, Identifier(scriptState, name), jsString(scriptState, value), slot); - return handleException(scriptState); + jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsString(m_scriptState, value), slot); + return handleException(m_scriptState); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, const ScriptObject& value) +bool ScriptObject::set(const char* name, const ScriptObject& value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - jsObject()->put(scriptState, Identifier(scriptState, name), value.jsObject(), slot); - return handleException(scriptState); + jsObject()->put(m_scriptState, Identifier(m_scriptState, name), value.jsObject(), slot); + return handleException(m_scriptState); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, const String& value) +bool ScriptObject::set(const char* name, const String& value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - jsObject()->put(scriptState, Identifier(scriptState, name), jsString(scriptState, value), slot); - return handleException(scriptState); + jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsString(m_scriptState, value), slot); + return handleException(m_scriptState); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, double value) +bool ScriptObject::set(const char* name, double value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - jsObject()->put(scriptState, Identifier(scriptState, name), jsNumber(scriptState, value), slot); - return handleException(scriptState); + jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsNumber(m_scriptState, value), slot); + return handleException(m_scriptState); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, long long value) +bool ScriptObject::set(const char* name, long long value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - jsObject()->put(scriptState, Identifier(scriptState, name), jsNumber(scriptState, value), slot); - return handleException(scriptState); + jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsNumber(m_scriptState, value), slot); + return handleException(m_scriptState); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, int value) +bool ScriptObject::set(const char* name, int value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - jsObject()->put(scriptState, Identifier(scriptState, name), jsNumber(scriptState, value), slot); - return handleException(scriptState); + jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsNumber(m_scriptState, value), slot); + return handleException(m_scriptState); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, bool value) +bool ScriptObject::set(const char* name, bool value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - jsObject()->put(scriptState, Identifier(scriptState, name), jsBoolean(value), slot); - return handleException(scriptState); + jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsBoolean(value), slot); + return handleException(m_scriptState); } ScriptObject ScriptObject::createNew(ScriptState* scriptState) { - JSLock lock(false); - return ScriptObject(constructEmptyObject(scriptState)); + JSLock lock(SilenceAssertionsOnly); + return ScriptObject(scriptState, constructEmptyObject(scriptState)); } bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, const ScriptObject& value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); scriptState->lexicalGlobalObject()->putDirect(Identifier(scriptState, name), value.jsObject()); return handleException(scriptState); } +#ifdef MANUAL_MERGE_REQUIRED #if ENABLE(JAVASCRIPT_DEBUGGER) bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorController* value) +#else // MANUAL_MERGE_REQUIRED +bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorBackend* value) +#endif // MANUAL_MERGE_REQUIRED { - JSLock lock(false); - scriptState->lexicalGlobalObject()->putDirect(Identifier(scriptState, name), toJS(scriptState, value)); + JSLock lock(SilenceAssertionsOnly); + JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); + globalObject->putDirect(Identifier(scriptState, name), toJS(scriptState, globalObject, value)); return handleException(scriptState); } #endif bool ScriptGlobalObject::get(ScriptState* scriptState, const char* name, ScriptObject& value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSValue jsValue = scriptState->lexicalGlobalObject()->get(scriptState, Identifier(scriptState, name)); if (!jsValue) return false; @@ -145,13 +155,13 @@ bool ScriptGlobalObject::get(ScriptState* scriptState, const char* name, ScriptO if (!jsValue.isObject()) return false; - value = ScriptObject(asObject(jsValue)); + value = ScriptObject(scriptState, asObject(jsValue)); return true; } bool ScriptGlobalObject::remove(ScriptState* scriptState, const char* name) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); scriptState->lexicalGlobalObject()->deleteProperty(scriptState, Identifier(scriptState, name)); return handleException(scriptState); } diff --git a/WebCore/bindings/js/ScriptObject.h b/WebCore/bindings/js/ScriptObject.h index ed86659..50b63ad 100644 --- a/WebCore/bindings/js/ScriptObject.h +++ b/WebCore/bindings/js/ScriptObject.h @@ -38,29 +38,32 @@ #include <runtime/Protect.h> namespace WebCore { - class InspectorController; + class InspectorBackend; class ScriptObject : public ScriptValue { public: - ScriptObject(JSC::JSObject*); + ScriptObject(ScriptState*, JSC::JSObject*); ScriptObject() {} JSC::JSObject* jsObject() const { return asObject(jsValue()); } - bool set(ScriptState*, const String& name, const String&); - bool set(ScriptState*, const char* name, const ScriptObject&); - bool set(ScriptState*, const char* name, const String&); - bool set(ScriptState*, const char* name, double); - bool set(ScriptState*, const char* name, long long); - bool set(ScriptState*, const char* name, int); - bool set(ScriptState*, const char* name, bool); + bool set(const String& name, const String&); + bool set(const char* name, const ScriptObject&); + bool set(const char* name, const String&); + bool set(const char* name, double); + bool set(const char* name, long long); + bool set(const char* name, int); + bool set(const char* name, bool); static ScriptObject createNew(ScriptState*); + + protected: + ScriptState* m_scriptState; }; class ScriptGlobalObject { public: static bool set(ScriptState*, const char* name, const ScriptObject&); - static bool set(ScriptState*, const char* name, InspectorController*); + static bool set(ScriptState*, const char* name, InspectorBackend*); static bool get(ScriptState*, const char* name, ScriptObject&); static bool remove(ScriptState*, const char* name); private: diff --git a/WebCore/bindings/js/ScriptObjectQuarantine.cpp b/WebCore/bindings/js/ScriptObjectQuarantine.cpp index 13e180a..89553ef 100644 --- a/WebCore/bindings/js/ScriptObjectQuarantine.cpp +++ b/WebCore/bindings/js/ScriptObjectQuarantine.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "ScriptObjectQuarantine.h" -#include "Database.h" #include "Document.h" #include "Frame.h" #include "JSDOMBinding.h" @@ -43,6 +42,7 @@ #include <runtime/JSLock.h> #if ENABLE(DATABASE) +#include "Database.h" #include "JSDatabase.h" #endif @@ -56,7 +56,7 @@ namespace WebCore { ScriptValue quarantineValue(ScriptState* scriptState, const ScriptValue& value) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); return ScriptValue(JSInspectedObjectWrapper::wrap(scriptState, value.jsValue())); } @@ -69,10 +69,11 @@ bool getQuarantinedScriptObject(Database* database, ScriptObject& quarantinedObj if (!frame) return false; - ExecState* exec = toJSDOMWindow(frame)->globalExec(); + JSDOMGlobalObject* globalObject = toJSDOMWindow(frame); + ExecState* exec = globalObject->globalExec(); - JSLock lock(false); - quarantinedObject = ScriptObject(asObject(JSInspectedObjectWrapper::wrap(exec, toJS(exec, database)))); + JSLock lock(SilenceAssertionsOnly); + quarantinedObject = ScriptObject(exec, asObject(JSInspectedObjectWrapper::wrap(exec, toJS(exec, globalObject, database)))); return true; } @@ -84,10 +85,11 @@ bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& qu ASSERT(frame); ASSERT(storage); - ExecState* exec = toJSDOMWindow(frame)->globalExec(); + JSDOMGlobalObject* globalObject = toJSDOMWindow(frame); + ExecState* exec = globalObject->globalExec(); - JSLock lock(false); - quarantinedObject = ScriptObject(asObject(JSInspectedObjectWrapper::wrap(exec, toJS(exec, storage)))); + JSLock lock(SilenceAssertionsOnly); + quarantinedObject = ScriptObject(exec, asObject(JSInspectedObjectWrapper::wrap(exec, toJS(exec, globalObject, storage)))); return true; } @@ -99,8 +101,9 @@ bool getQuarantinedScriptObject(Node* node, ScriptObject& quarantinedObject) if (!exec) return false; - JSLock lock(false); - quarantinedObject = ScriptObject(asObject(JSInspectedObjectWrapper::wrap(exec, toJS(exec, node)))); + JSLock lock(SilenceAssertionsOnly); + // FIXME: Should use some sort of globalObjectFromNode() + quarantinedObject = ScriptObject(exec, asObject(JSInspectedObjectWrapper::wrap(exec, toJS(exec, deprecatedGlobalObjectForPrototype(exec), node)))); return true; } @@ -112,8 +115,8 @@ bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedO JSDOMWindow* window = toJSDOMWindow(domWindow->frame()); ExecState* exec = window->globalExec(); - JSLock lock(false); - quarantinedObject = ScriptObject(asObject(JSInspectedObjectWrapper::wrap(exec, window))); + JSLock lock(SilenceAssertionsOnly); + quarantinedObject = ScriptObject(exec, asObject(JSInspectedObjectWrapper::wrap(exec, window))); return true; } diff --git a/WebCore/bindings/js/ScriptSourceCode.h b/WebCore/bindings/js/ScriptSourceCode.h index 4a2403d..1b05ded 100644 --- a/WebCore/bindings/js/ScriptSourceCode.h +++ b/WebCore/bindings/js/ScriptSourceCode.h @@ -32,20 +32,24 @@ #define ScriptSourceCode_h #include "CachedScriptSourceProvider.h" +#include "ScriptSourceProvider.h" #include "StringSourceProvider.h" #include "KURL.h" +#include <wtf/RefPtr.h> namespace WebCore { class ScriptSourceCode { public: ScriptSourceCode(const String& source, const KURL& url = KURL(), int startLine = 1) - : m_code(makeSource(source, url.isNull() ? String() : url.string(), startLine)) + : m_provider(StringSourceProvider::create(source, url.isNull() ? String() : url.string())) + , m_code(m_provider, startLine) { } ScriptSourceCode(CachedScript* cs) - : m_code(makeSource(cs)) + : m_provider(CachedScriptSourceProvider::create(cs)) + , m_code(m_provider) { } @@ -53,7 +57,11 @@ public: const JSC::SourceCode& jsSourceCode() const { return m_code; } + const String& source() const { return m_provider->source(); } + private: + RefPtr<ScriptSourceProvider> m_provider; + JSC::SourceCode m_code; }; diff --git a/WebCore/bindings/js/ScriptSourceProvider.h b/WebCore/bindings/js/ScriptSourceProvider.h new file mode 100644 index 0000000..3fe3584 --- /dev/null +++ b/WebCore/bindings/js/ScriptSourceProvider.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 Daniel Bates (dbates@intudata.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScriptSourceProvider_h +#define ScriptSourceProvider_h + +#include <parser/SourceProvider.h> + +namespace WebCore { + + class String; + + class ScriptSourceProvider : public JSC::SourceProvider { + public: + ScriptSourceProvider(const JSC::UString& url, JSC::SourceBOMPresence hasBOMs = JSC::SourceCouldHaveBOMs) + : SourceProvider(url, hasBOMs) + { + } + + virtual const String& source() const = 0; + }; + +} // namespace WebCore + +#endif // ScriptSourceProvider_h diff --git a/WebCore/bindings/js/ScriptValue.cpp b/WebCore/bindings/js/ScriptValue.cpp index dfb46da..d427cee 100644 --- a/WebCore/bindings/js/ScriptValue.cpp +++ b/WebCore/bindings/js/ScriptValue.cpp @@ -44,7 +44,7 @@ bool ScriptValue::getString(String& result) const { if (!m_value) return false; - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); UString ustring; if (!m_value.get().getString(ustring)) return false; diff --git a/WebCore/bindings/js/StringSourceProvider.h b/WebCore/bindings/js/StringSourceProvider.h index ab37a56..770c4fc 100644 --- a/WebCore/bindings/js/StringSourceProvider.h +++ b/WebCore/bindings/js/StringSourceProvider.h @@ -29,21 +29,23 @@ #ifndef StringSourceProvider_h #define StringSourceProvider_h +#include "ScriptSourceProvider.h" #include <parser/SourceCode.h> namespace WebCore { - class StringSourceProvider : public JSC::SourceProvider { + class StringSourceProvider : public ScriptSourceProvider { public: static PassRefPtr<StringSourceProvider> create(const String& source, const String& url) { return adoptRef(new StringSourceProvider(source, url)); } JSC::UString getRange(int start, int end) const { return JSC::UString(m_source.characters() + start, end - start); } const UChar* data() const { return m_source.characters(); } int length() const { return m_source.length(); } + const String& source() const { return m_source; } private: StringSourceProvider(const String& source, const String& url) - : SourceProvider(url) + : ScriptSourceProvider(url) , m_source(source) { } diff --git a/WebCore/bindings/js/WorkerScriptController.cpp b/WebCore/bindings/js/WorkerScriptController.cpp index bcf107b..3590dad 100644 --- a/WebCore/bindings/js/WorkerScriptController.cpp +++ b/WebCore/bindings/js/WorkerScriptController.cpp @@ -31,7 +31,8 @@ #include "WorkerScriptController.h" #include "JSDOMBinding.h" -#include "JSWorkerContext.h" +#include "JSDedicatedWorkerContext.h" +#include "JSSharedWorkerContext.h" #include "ScriptSourceCode.h" #include "ScriptValue.h" #include "WorkerContext.h" @@ -66,16 +67,30 @@ void WorkerScriptController::initScript() { ASSERT(!m_workerContextWrapper); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); // Explicitly protect the global object's prototype so it isn't collected // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) - RefPtr<Structure> prototypeStructure = JSWorkerContextPrototype::createStructure(jsNull()); - ProtectedPtr<JSWorkerContextPrototype> prototype = new (m_globalData.get()) JSWorkerContextPrototype(prototypeStructure.release()); - - RefPtr<Structure> structure = JSWorkerContext::createStructure(prototype); - m_workerContextWrapper = new (m_globalData.get()) JSWorkerContext(structure.release(), m_workerContext); + RefPtr<Structure> workerContextPrototypeStructure = JSWorkerContextPrototype::createStructure(jsNull()); + ProtectedPtr<JSWorkerContextPrototype> workerContextPrototype = new (m_globalData.get()) JSWorkerContextPrototype(workerContextPrototypeStructure.release()); + + if (m_workerContext->isDedicatedWorkerContext()) { + RefPtr<Structure> dedicatedContextPrototypeStructure = JSDedicatedWorkerContextPrototype::createStructure(workerContextPrototype); + ProtectedPtr<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype = new (m_globalData.get()) JSDedicatedWorkerContextPrototype(dedicatedContextPrototypeStructure.release()); + RefPtr<Structure> structure = JSDedicatedWorkerContext::createStructure(dedicatedContextPrototype); + + m_workerContextWrapper = new (m_globalData.get()) JSDedicatedWorkerContext(structure.release(), m_workerContext->toDedicatedWorkerContext()); +#if ENABLE(SHARED_WORKERS) + } else { + ASSERT(m_workerContext->isSharedWorkerContext()); + RefPtr<Structure> sharedContextPrototypeStructure = JSSharedWorkerContextPrototype::createStructure(workerContextPrototype); + ProtectedPtr<JSSharedWorkerContextPrototype> sharedContextPrototype = new (m_globalData.get()) JSSharedWorkerContextPrototype(sharedContextPrototypeStructure.release()); + RefPtr<Structure> structure = JSSharedWorkerContext::createStructure(sharedContextPrototype); + + m_workerContextWrapper = new (m_globalData.get()) JSSharedWorkerContext(structure.release(), m_workerContext->toSharedWorkerContext()); +#endif + } } ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode) @@ -88,7 +103,7 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode) ScriptValue exception; ScriptValue result = evaluate(sourceCode, &exception); if (exception.jsValue()) { - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); reportException(m_workerContextWrapper->globalExec(), exception.jsValue()); } return result; @@ -103,15 +118,13 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, } initScriptIfNeeded(); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); ExecState* exec = m_workerContextWrapper->globalExec(); m_workerContextWrapper->globalData()->timeoutChecker.start(); Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), sourceCode.jsSourceCode(), m_workerContextWrapper); m_workerContextWrapper->globalData()->timeoutChecker.stop(); - m_workerContext->thread()->workerObjectProxy().reportPendingActivity(m_workerContext->hasPendingActivity()); - if (comp.complType() == Normal || comp.complType() == ReturnValue) return comp.value(); diff --git a/WebCore/bindings/js/WorkerScriptController.h b/WebCore/bindings/js/WorkerScriptController.h index 0454721..bb33f60 100644 --- a/WebCore/bindings/js/WorkerScriptController.h +++ b/WebCore/bindings/js/WorkerScriptController.h @@ -45,7 +45,7 @@ namespace WebCore { class String; class WorkerContext; - class WorkerScriptController : Noncopyable { + class WorkerScriptController : public Noncopyable { public: WorkerScriptController(WorkerContext*); ~WorkerScriptController(); diff --git a/WebCore/bindings/objc/DOM.mm b/WebCore/bindings/objc/DOM.mm index 3fd28d1..62bf1de 100644 --- a/WebCore/bindings/objc/DOM.mm +++ b/WebCore/bindings/objc/DOM.mm @@ -468,7 +468,7 @@ id <DOMEventTarget> kit(WebCore::EventTarget* eventTarget) ASSERT(name); WebCore::Element* element = core(self); ASSERT(element); - return element->document()->completeURL(parseURL(element->getAttribute(name))); + return element->document()->completeURL(deprecatedParseURL(element->getAttribute(name))); } - (BOOL)isFocused @@ -503,6 +503,21 @@ id <DOMEventTarget> kit(WebCore::EventTarget* eventTarget) @end //------------------------------------------------------------------------------------------ +// DOMRGBColor + +@implementation DOMRGBColor (WebPrivate) + +// FIXME: This should be removed as soon as all internal Apple uses of it have been replaced with +// calls to the public method - (NSColor *)color. +- (NSColor *)_color +{ + return [self color]; +} + +@end + + +//------------------------------------------------------------------------------------------ // DOMNodeFilter DOMNodeFilter *kit(WebCore::NodeFilter* impl) diff --git a/WebCore/bindings/objc/DOMHTML.mm b/WebCore/bindings/objc/DOMHTML.mm index 8c0d30b..1043d8e 100644 --- a/WebCore/bindings/objc/DOMHTML.mm +++ b/WebCore/bindings/objc/DOMHTML.mm @@ -70,7 +70,7 @@ - (DOMDocumentFragment *)_createDocumentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString { - NSURL *baseURL = core(self)->completeURL(WebCore::parseURL(baseURLString)); + NSURL *baseURL = core(self)->completeURL(WebCore::deprecatedParseURL(baseURLString)); return [self createDocumentFragmentWithMarkupString:markupString baseURL:baseURL]; } diff --git a/WebCore/bindings/objc/DOMInternal.mm b/WebCore/bindings/objc/DOMInternal.mm index eb98a8a..9b26e59 100644 --- a/WebCore/bindings/objc/DOMInternal.mm +++ b/WebCore/bindings/objc/DOMInternal.mm @@ -123,11 +123,13 @@ void removeDOMWrapper(DOMObjectInternal* impl) frame = document->frame(); if (!frame) return; - - JSC::ExecState *exec = frame->script()->globalObject()->globalExec(); - + + // The global object which should own this node. + WebCore::JSDOMGlobalObject* globalObject = frame->script()->globalObject(); + JSC::ExecState *exec = globalObject->globalExec(); + // Get (or create) a cached JS object for the DOM node. - JSC::JSObject *scriptImp = asObject(WebCore::toJS(exec, nodeImpl)); + JSC::JSObject *scriptImp = asObject(WebCore::toJS(exec, globalObject, nodeImpl)); JSC::Bindings::RootObject* rootObject = frame->script()->bindingRootObject(); diff --git a/WebCore/bindings/objc/DOMRGBColor.mm b/WebCore/bindings/objc/DOMRGBColor.mm deleted file mode 100644 index 27f8966..0000000 --- a/WebCore/bindings/objc/DOMRGBColor.mm +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "config.h" -#import "DOMInternal.h" // import first to make the private/public trick work -#import "DOMRGBColorInternal.h" - -#import "CSSPrimitiveValue.h" -#import "ColorMac.h" -#import "DOMCSSPrimitiveValueInternal.h" -#import "WebCoreObjCExtras.h" -#import "WebScriptObjectPrivate.h" -#import <runtime/InitializeThreading.h> - -static NSMapTable* RGBColorWrapperCache; - -static id getWrapperForRGB(WebCore::RGBA32 value) -{ - if (!RGBColorWrapperCache) - return nil; - return static_cast<id>(NSMapGet(RGBColorWrapperCache, reinterpret_cast<const void*>(value))); -} - -static void setWrapperForRGB(id wrapper, WebCore::RGBA32 value) -{ - if (!RGBColorWrapperCache) - // No need to retain/free either impl key, or id value. Items will be removed - // from the cache in dealloc methods. - RGBColorWrapperCache = createWrapperCacheWithIntegerKeys(); - NSMapInsert(RGBColorWrapperCache, reinterpret_cast<const void*>(value), wrapper); -} - -static void removeWrapperForRGB(WebCore::RGBA32 value) -{ - if (!RGBColorWrapperCache) - return; - NSMapRemove(RGBColorWrapperCache, reinterpret_cast<const void*>(value)); -} - -@implementation DOMRGBColor - -+ (void)initialize -{ - JSC::initializeThreading(); -#ifndef BUILDING_ON_TIGER - WebCoreObjCFinalizeOnMainThread(self); -#endif -} - -- (void)dealloc -{ - if (WebCoreObjCScheduleDeallocateOnMainThread([DOMRGBColor class], self)) - return; - - removeWrapperForRGB(reinterpret_cast<uintptr_t>(_internal)); - _internal = 0; - [super dealloc]; -} - -- (DOMCSSPrimitiveValue *)red -{ - WebCore::RGBA32 rgb = reinterpret_cast<uintptr_t>(_internal); - int value = (rgb >> 16) & 0xFF; - return kit(WebCore::CSSPrimitiveValue::create(value, WebCore::CSSPrimitiveValue::CSS_NUMBER).get()); -} - -- (DOMCSSPrimitiveValue *)green -{ - WebCore::RGBA32 rgb = reinterpret_cast<uintptr_t>(_internal); - int value = (rgb >> 8) & 0xFF; - return kit(WebCore::CSSPrimitiveValue::create(value, WebCore::CSSPrimitiveValue::CSS_NUMBER).get()); -} - -- (DOMCSSPrimitiveValue *)blue -{ - WebCore::RGBA32 rgb = reinterpret_cast<uintptr_t>(_internal); - int value = rgb & 0xFF; - return kit(WebCore::CSSPrimitiveValue::create(value, WebCore::CSSPrimitiveValue::CSS_NUMBER).get()); -} - -- (DOMCSSPrimitiveValue *)alpha -{ - WebCore::RGBA32 rgb = reinterpret_cast<uintptr_t>(_internal); - float value = static_cast<float>(WebCore::Color(rgb).alpha()) / 0xFF; - return kit(WebCore::CSSPrimitiveValue::create(value, WebCore::CSSPrimitiveValue::CSS_NUMBER).get()); - -} - -- (NSColor *)color -{ - WebCore::RGBA32 rgb = reinterpret_cast<uintptr_t>(_internal); - return WebCore::nsColor(WebCore::Color(rgb)); -} - -@end - -@implementation DOMRGBColor (WebPrivate) - -// FIXME: this should be removed once all internal Apple uses of it have been replaced with -// calls to the public method, color without the leading underscore. -- (NSColor *)_color -{ - return [self color]; -} - -@end - -WebCore::RGBA32 core(DOMRGBColor *color) -{ - return color ? static_cast<WebCore::RGBA32>(reinterpret_cast<uintptr_t>(color->_internal)) : 0; -} - -DOMRGBColor *kit(WebCore::RGBA32 value) -{ - if (DOMRGBColor *wrapper = getWrapperForRGB(value)) - return [[wrapper retain] autorelease]; - - DOMRGBColor *wrapper = [[DOMRGBColor alloc] _init]; - wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(value); - setWrapperForRGB(wrapper, value); - return [wrapper autorelease]; -} diff --git a/WebCore/bindings/objc/WebScriptObject.mm b/WebCore/bindings/objc/WebScriptObject.mm index 8889eac..1086204 100644 --- a/WebCore/bindings/objc/WebScriptObject.mm +++ b/WebCore/bindings/objc/WebScriptObject.mm @@ -280,7 +280,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root if (![self _isSafeScript]) return nil; - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); // Look up the function object. ExecState* exec = [self _rootObject]->globalObject()->globalExec(); @@ -325,7 +325,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root ASSERT(!exec->hadException()); JSValue result; - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); [self _rootObject]->globalObject()->globalData()->timeoutChecker.start(); Completion completion = JSC::evaluate([self _rootObject]->globalObject()->globalExec(), [self _rootObject]->globalObject()->globalScopeChain(), makeSource(String(script))); @@ -360,7 +360,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root ExecState* exec = [self _rootObject]->globalObject()->globalExec(); ASSERT(!exec->hadException()); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; [self _imp]->put(exec, Identifier(exec, String(key)), convertObjcValueToValue(exec, &value, ObjcObjectType, [self _rootObject]), slot); @@ -386,7 +386,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root // Need to scope this lock to ensure that we release the lock before calling // [super valueForKey:key] which might throw an exception and bypass the JSLock destructor, // leaving the lock permanently held - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSValue result = [self _imp]->get(exec, Identifier(exec, String(key))); @@ -402,7 +402,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root if ([resultObj isKindOfClass:[WebUndefined class]]) resultObj = [super valueForKey:key]; // defaults to throwing an exception - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); _didExecute(self); return resultObj; @@ -416,7 +416,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root ExecState* exec = [self _rootObject]->globalObject()->globalExec(); ASSERT(!exec->hadException()); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); [self _imp]->deleteProperty(exec, Identifier(exec, String(key))); if (exec->hadException()) { @@ -434,7 +434,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root return @"Undefined"; } - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); ExecState* exec = [self _rootObject]->globalObject()->globalExec(); id result = convertValueToObjcValue(exec, [self _imp], ObjcObjectType).objectValue; @@ -454,7 +454,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root ExecState* exec = [self _rootObject]->globalObject()->globalExec(); ASSERT(!exec->hadException()); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); JSValue result = [self _imp]->get(exec, index); if (exec->hadException()) { @@ -478,7 +478,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root ExecState* exec = [self _rootObject]->globalObject()->globalExec(); ASSERT(!exec->hadException()); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); [self _imp]->put(exec, index, convertObjcValueToValue(exec, &value, ObjcObjectType, [self _rootObject])); if (exec->hadException()) { @@ -509,7 +509,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root if (value.isObject()) { JSObject* object = asObject(value); ExecState* exec = rootObject->globalObject()->globalExec(); - JSLock lock(false); + JSLock lock(SilenceAssertionsOnly); if (object->classInfo() != &RuntimeObjectImp::s_info) { JSValue runtimeObject = object->get(exec, Identifier(exec, "__apple_runtime_object")); diff --git a/WebCore/bindings/scripts/CodeGenerator.pm b/WebCore/bindings/scripts/CodeGenerator.pm index d217c37..341c607 100644 --- a/WebCore/bindings/scripts/CodeGenerator.pm +++ b/WebCore/bindings/scripts/CodeGenerator.pm @@ -40,7 +40,7 @@ my %primitiveTypeHash = ("int" => 1, "short" => 1, "long" => 1, "long long" => 1 "float" => 1, "double" => 1, "boolean" => 1, "void" => 1); -my %podTypeHash = ("RGBColor" => 1, "SVGNumber" => 1, "SVGTransform" => 1); +my %podTypeHash = ("SVGNumber" => 1, "SVGTransform" => 1); my %podTypesWithWritablePropertiesHash = ("SVGLength" => 1, "SVGMatrix" => 1, "SVGPoint" => 1, "SVGRect" => 1); my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1); @@ -116,6 +116,41 @@ sub ProcessDocument $codeGenerator->finish(); } +# Necessary for V8 bindings to determine whether an interface is descendant from Node. +# Node descendants are treated differently by DOMMap and this allows inferring the +# type statically. See more at the original change: http://codereview.chromium.org/3195. +# FIXME: Figure out a way to eliminate this JS bindings dichotomy. +sub FindParentsRecursively +{ + my $object = shift; + my $dataNode = shift; + my @parents = ($dataNode->name); + foreach (@{$dataNode->parents}) { + my $interface = $object->StripModule($_); + + $endCondition = 0; + $foundFilename = ""; + foreach (@{$useDirectories}) { + $object->ScanDirectory("$interface.idl", $_, $_, 0) if ($foundFilename eq ""); + } + + if ($foundFilename ne "") { + print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interface\"\n" if $verbose; + + # Step #2: Parse the found IDL file (in quiet mode). + my $parser = IDLParser->new(1); + my $document = $parser->Parse($foundFilename, $defines, $preprocessor, 1); + + foreach my $class (@{$document->classes}) { + @parents = (@parents, FindParentsRecursively($object, $class)); + } + } else { + die("Could NOT find specified parent interface \"$interface\"!\n") + } + } + return @parents; +} + sub AddMethodsConstantsAndAttributesFromParentClasses { # For the passed interface, recursively parse all parent diff --git a/WebCore/bindings/scripts/CodeGeneratorCOM.pm b/WebCore/bindings/scripts/CodeGeneratorCOM.pm index 7e80a17..6641305 100644 --- a/WebCore/bindings/scripts/CodeGeneratorCOM.pm +++ b/WebCore/bindings/scripts/CodeGeneratorCOM.pm @@ -596,9 +596,15 @@ sub GenerateCPPAttribute # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT - my $setterCall = " impl${implementationClassWithoutNamespace}()->${setterName}(" . join(", ", @setterParams) . ");\n"; - - push(@setterImplementation, $setterCall); + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + $CPPImplementationWebCoreIncludes{"HTMLNames.h"} = 1; + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); + push(@setterImplementation, " impl${implementationClassWithoutNamespace}()->setAttribute(WebCore::HTMLNames::${contentAttributeName}Attr, " . join(", ", @setterParams) . ");\n"); + } else { + push(@setterImplementation, " impl${implementationClassWithoutNamespace}()->${setterName}(" . join(", ", @setterParams) . ");\n"); + } push(@setterImplementation, " return S_OK;\n"); push(@setterImplementation, "}\n\n"); @@ -611,7 +617,17 @@ sub GenerateCPPAttribute push(@getterImplementation, " if (!result)\n"); push(@getterImplementation, " return E_POINTER;\n\n"); - my $implementationGetter = "impl${implementationClassWithoutNamespace}()->" . $codeGenerator->WK_lcfirst($attributeName) . "(" . ($hasGetterException ? "ec" : ""). ")"; + my $implementationGetter; + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + $implIncludes{"HTMLNames.h"} = 1; + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); + my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; + $implementationGetter = "impl${implementationClassWithoutNamespace}()->${getAttributeFunctionName}(WebCore::HTMLNames::${contentAttributeName}Attr)"; + } else { + $implementationGetter = "impl${implementationClassWithoutNamespace}()->" . $codeGenerator->WK_lcfirst($attributeName) . "(" . ($hasGetterException ? "ec" : ""). ")"; + } push(@getterImplementation, " WebCore::ExceptionCode ec = 0;\n") if $hasGetterException; diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm index 4563018..1918aef 100644 --- a/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -34,7 +34,6 @@ my %headerIncludes = (); my @implContentHeader = (); my @implContent = (); my %implIncludes = (); -my %implKJSIncludes = (); # Default .h template my $headerTemplate = << "EOF"; @@ -120,7 +119,15 @@ sub GetParentClassName my $dataNode = shift; return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"}; - return "DOMObject" if @{$dataNode->parents} eq 0; + if (@{$dataNode->parents} eq 0) { + # FIXME: SVG types requiring a context() pointer do not have enough + # space to hold a globalObject pointer as well w/o hitting the CELL_SIZE limit. + # This could be fixed by moving context() into the various impl() classes. + # Until then, we special case these SVG bindings and allow them to return + # the wrong prototypes and constructors during x-frame access. See bug 27088. + return "DOMObjectWithSVGContext" if IsSVGTypeNeedingContextParameter($dataNode->name); + return "DOMObjectWithGlobalPointer"; + } return "JS" . $codeGenerator->StripModule($dataNode->parents(0)); } @@ -141,14 +148,6 @@ sub AvoidInclusionOfType return 0; } -sub UsesManualToJSImplementation -{ - my $type = shift; - - return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or $type eq "Event" or $type eq "ImageData" or $type eq "Element" or $type eq "Text" or $type eq "SVGElementInstance"; - return 0; -} - sub IndexGetterReturnsStrings { my $type = shift; @@ -174,7 +173,7 @@ sub AddIncludesForType # When we're finished with the one-file-per-class # reorganization, we won't need these special cases. if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type) - or $type eq "DOMString" or $type eq "DOMObject" or $type eq "RGBColor" or $type eq "Array") { + or $type eq "DOMString" or $type eq "DOMObject" or $type eq "Array") { } elsif ($type =~ /SVGPathSeg/) { $joinedName = $type; $joinedName =~ s/Abs|Rel//; @@ -220,7 +219,7 @@ sub AddClassForwardIfNeeded { my $implClassName = shift; - # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them! + # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them! push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName); } @@ -228,11 +227,13 @@ sub IsSVGTypeNeedingContextParameter { my $implClassName = shift; - if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) { - return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/; + return 0 unless $implClassName =~ /SVG/; + return 0 if $implClassName =~ /Element/; + my @noContextNeeded = ("SVGPaint", "SVGColor", "SVGDocument", "SVGZoomEvent"); + foreach (@noContextNeeded) { + return 0 if $implClassName eq $_; } - - return 0; + return 1; } sub HashValueForClassAndName @@ -328,8 +329,8 @@ sub GenerateGetOwnPropertySlotBody &$manualLookupGetterGeneration(); } - if ($dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { - push(@getOwnPropertySlotImpl, " if (customGetOwnPropertySlot(exec, propertyName, slot))\n"); + if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) { + push(@getOwnPropertySlotImpl, " if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n"); push(@getOwnPropertySlotImpl, " return true;\n"); } @@ -367,6 +368,7 @@ sub GenerateHeader my $hasParent = $hasLegacyParent || $hasRealParent; my $parentClassName = GetParentClassName($dataNode); my $conditional = $dataNode->extendedAttributes->{"Conditional"}; + my $needsSVGContext = IsSVGTypeNeedingContextParameter($interfaceName); # - Add default header template @headerContentHeader = split("\r", $headerTemplate); @@ -378,36 +380,39 @@ sub GenerateHeader my $conditionalString; if ($conditional) { $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; - push(@headerContentHeader, "\n#if ${conditionalString}\n\n"); + push(@headerContentHeader, "#if ${conditionalString}\n\n"); } if ($hasParent) { - push(@headerContentHeader, "#include \"$parentClassName.h\"\n"); + $headerIncludes{"$parentClassName.h"} = 1; } else { - push(@headerContentHeader, "#include \"JSDOMBinding.h\"\n"); - push(@headerContentHeader, "#include <runtime/JSGlobalObject.h>\n"); - push(@headerContentHeader, "#include <runtime/ObjectPrototype.h>\n"); + $headerIncludes{"DOMObjectWithSVGContext.h"} = $needsSVGContext; + $headerIncludes{"JSDOMBinding.h"} = !$needsSVGContext; + $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1; + $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1; } if ($dataNode->extendedAttributes->{"CustomCall"}) { - push(@headerContentHeader, "#include <runtime/CallData.h>\n"); + $headerIncludes{"<runtime/CallData.h>"} = 1; } if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) { - push(@headerContentHeader, "#include <runtime/Lookup.h>\n"); - push(@headerContentHeader, "#include <wtf/AlwaysInline.h>\n"); + $headerIncludes{"<runtime/Lookup.h>"} = 1; + $headerIncludes{"<wtf/AlwaysInline.h>"} = 1; } if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) { - push(@headerContentHeader, "#include \"${implClassName}.h\""); + $headerIncludes{"$implClassName.h"} = 1; } + $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/; + # Get correct pass/store types respecting PODType flag my $podType = $dataNode->extendedAttributes->{"PODType"}; my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; - push(@headerContentHeader, "#include \"$podType.h\"\n") if $podType and $podType ne "float"; + $headerIncludes{"$podType.h"} = 1 if $podType and $podType ne "float"; - push(@headerContentHeader, "#include \"JSSVGPODTypeWrapper.h\"\n") if $podType; + $headerIncludes{"JSSVGPODTypeWrapper.h"} = 1 if $podType; my $numConstants = @{$dataNode->constants}; my $numAttributes = @{$dataNode->attributes}; @@ -427,10 +432,12 @@ sub GenerateHeader # Constructor if ($interfaceName eq "DOMWindow") { push(@headerContent, " $className(PassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n"); + } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { + push(@headerContent, " $className(PassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n"); } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@headerContent, " $className(PassRefPtr<JSC::Structure>, PassRefPtr<$implType>, SVGElement* context);\n"); + push(@headerContent, " $className(PassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>, SVGElement* context);\n"); } else { - push(@headerContent, " $className(PassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n"); + push(@headerContent, " $className(PassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n"); } # Destructor @@ -439,13 +446,14 @@ sub GenerateHeader # Prototype push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}); - $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"}; + $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"}; my $hasGetter = $numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"} + || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"} || $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}; @@ -453,7 +461,7 @@ sub GenerateHeader if ($hasGetter) { push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n"); push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}; - push(@headerContent, " bool customGetOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}; } # Check if we have any writable properties @@ -466,13 +474,14 @@ sub GenerateHeader my $hasSetter = $hasReadWriteProperties || $dataNode->extendedAttributes->{"CustomPutFunction"} + || $dataNode->extendedAttributes->{"DelegatingPutFunction"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; # Getters if ($hasSetter) { push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); push(@headerContent, " virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; - push(@headerContent, " bool customPut(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"CustomPutFunction"}; + push(@headerContent, " bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPutFunction"}; } # Class info @@ -495,7 +504,7 @@ sub GenerateHeader } # Custom mark function - push(@headerContent, " virtual void mark();\n\n") if $dataNode->extendedAttributes->{"CustomMarkFunction"}; + push(@headerContent, " virtual void markChildren(JSC::MarkStack&);\n\n") if $dataNode->extendedAttributes->{"CustomMarkFunction"}; # Custom pushEventHandlerScope function push(@headerContent, " virtual void pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChain&) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"}; @@ -508,7 +517,6 @@ sub GenerateHeader # Custom getPropertyNames function push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}); - push(@headerContent, " bool customGetPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if $dataNode->extendedAttributes->{"CustomGetPropertyNames"}; # Custom getPropertyAttributes function push(@headerContent, " virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned& attributes) const;\n") if $dataNode->extendedAttributes->{"CustomGetPropertyAttributes"}; @@ -526,7 +534,7 @@ sub GenerateHeader push(@headerContent, " virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"}; # Constructor object getter - push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*);\n") if $dataNode->extendedAttributes->{"GenerateConstructor"}; + push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if $dataNode->extendedAttributes->{"GenerateConstructor"}; my $numCustomFunctions = 0; my $numCustomAttributes = 0; @@ -575,23 +583,11 @@ sub GenerateHeader } if (!$hasParent) { - if ($podType) { - push(@headerContent, " JSSVGPODTypeWrapper<$podType>* impl() const { return m_impl.get(); }\n"); - push(@headerContent, " SVGElement* context() const { return m_context.get(); }\n\n"); - push(@headerContent, "private:\n"); - push(@headerContent, " RefPtr<SVGElement> m_context;\n"); - push(@headerContent, " RefPtr<JSSVGPODTypeWrapper<$podType> > m_impl;\n"); - } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@headerContent, " $implClassName* impl() const { return m_impl.get(); }\n"); - push(@headerContent, " SVGElement* context() const { return m_context.get(); }\n\n"); - push(@headerContent, "private:\n"); - push(@headerContent, " RefPtr<SVGElement> m_context;\n"); - push(@headerContent, " RefPtr<$implClassName > m_impl;\n"); - } else { - push(@headerContent, " $implClassName* impl() const { return m_impl.get(); }\n\n"); - push(@headerContent, "private:\n"); - push(@headerContent, " RefPtr<$implClassName> m_impl;\n"); - } + # Extra space after JSSVGPODTypeWrapper<> to make RefPtr<Wrapper<> > compile. + my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; + push(@headerContent, " $implType* impl() const { return m_impl.get(); }\n\n"); + push(@headerContent, "private:\n"); + push(@headerContent, " RefPtr<$implType> m_impl;\n"); } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) { push(@headerContent, " $implClassName* impl() const\n"); push(@headerContent, " {\n"); @@ -620,20 +616,20 @@ sub GenerateHeader push(@headerContent, "};\n\n"); - if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) { + if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n"); push(@headerContent, "{\n"); push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1)); push(@headerContent, "}\n\n"); } - if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"}) { + if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) { if ($podType) { - push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSSVGPODTypeWrapper<$podType>*, SVGElement* context);\n"); + push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement* context);\n"); } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, $implType*, SVGElement* context);\n"); + push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement* context);\n"); } else { - push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, $implType*);\n"); + push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n"); } } if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) { @@ -646,7 +642,7 @@ sub GenerateHeader } } if ($interfaceName eq "Node" or $interfaceName eq "Element" or $interfaceName eq "Text" or $interfaceName eq "CDATASection") { - push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, $interfaceName*);\n"); + push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n"); } push(@headerContent, "\n"); @@ -657,16 +653,16 @@ sub GenerateHeader push(@headerContent, "public:\n"); if ($interfaceName eq "DOMWindow") { push(@headerContent, " void* operator new(size_t);\n"); - } elsif ($interfaceName eq "WorkerContext") { + } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { push(@headerContent, " void* operator new(size_t, JSC::JSGlobalData*);\n"); } else { push(@headerContent, " static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*);\n"); } push(@headerContent, " virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n"); push(@headerContent, " static const JSC::ClassInfo s_info;\n"); - if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"CustomPrototypeGetOwnPropertySlot"}) { + if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n"); - push(@headerContent, " bool customGetOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"CustomPrototypeGetOwnPropertySlot"}; + push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}; push(@headerContent, " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . @@ -674,9 +670,9 @@ sub GenerateHeader " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType));\n" . " }\n"); } - if ($dataNode->extendedAttributes->{"CustomPrototypePutFunction"}) { + if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); - push(@headerContent, " bool customPut(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n"); + push(@headerContent, " bool putDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);\n"); } # Custom defineGetter function @@ -741,25 +737,19 @@ sub GenerateImplementation # - Add default header template @implContentHeader = split("\r", $headerTemplate); - push(@implContentHeader, "\n#include \"config.h\"\n\n"); + + push(@implContentHeader, "\n#include \"config.h\"\n"); my $conditionalString; if ($conditional) { $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; push(@implContentHeader, "\n#if ${conditionalString}\n\n"); } - - if ($className =~ /^JSSVG/) { - push(@implContentHeader, "#include \"SVGElement.h\"\n"); - - if ($className =~ /^JSSVGAnimated/) { - AddIncludesForSVGAnimatedType($interfaceName); - } - } - push(@implContentHeader, "#include \"$className.h\"\n\n"); - push(@implContentHeader, "#include <wtf/GetPtr.h>\n\n"); - push(@implContentHeader, "#include <runtime/PropertyNameArray.h>\n") if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}; + AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/; + + $implIncludes{"<wtf/GetPtr.h>"} = 1; + $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}; AddIncludesForType($interfaceName); @@ -913,7 +903,7 @@ sub GenerateImplementation push(@implContent, "{\n"); push(@implContent, " return JSDOMWindow::commonJSGlobalData()->heap.allocate(size);\n"); push(@implContent, "}\n\n"); - } elsif ($interfaceName eq "WorkerContext") { + } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { push(@implContent, "void* ${className}Prototype::operator new(size_t size, JSGlobalData* globalData)\n"); push(@implContent, "{\n"); push(@implContent, " return globalData->heap.allocate(size);\n"); @@ -924,12 +914,12 @@ sub GenerateImplementation push(@implContent, " return getDOMPrototype<${className}>(exec, globalObject);\n"); push(@implContent, "}\n\n"); } - if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"CustomPrototypeGetOwnPropertySlot"}) { + if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); push(@implContent, "{\n"); - if ($dataNode->extendedAttributes->{"CustomPrototypeGetOwnPropertySlot"}) { - push(@implContent, " if (customGetOwnPropertySlot(exec, propertyName, slot))\n"); + if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) { + push(@implContent, " if (getOwnPropertySlotDelegate(exec, propertyName, slot))\n"); push(@implContent, " return true;\n"); } @@ -945,10 +935,10 @@ sub GenerateImplementation push(@implContent, "}\n\n"); } - if ($dataNode->extendedAttributes->{"CustomPrototypePutFunction"}) { + if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { push(@implContent, "void ${className}Prototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n"); push(@implContent, "{\n"); - push(@implContent, " if (customPut(exec, propertyName, value, slot))\n"); + push(@implContent, " if (putDelegate(exec, propertyName, value, slot))\n"); push(@implContent, " return;\n"); push(@implContent, " Base::put(exec, propertyName, value, slot);\n"); push(@implContent, "}\n\n"); @@ -992,22 +982,18 @@ sub GenerateImplementation AddIncludesForType("JSDOMWindowShell"); push(@implContent, "${className}::$className(PassRefPtr<Structure> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n"); push(@implContent, " : $parentClassName(structure, impl, shell)\n"); + } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { + AddIncludesForType($interfaceName); + push(@implContent, "${className}::$className(PassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n"); + push(@implContent, " : $parentClassName(structure, impl)\n"); } else { - my $contextArg = ""; - if ($needsSVGContext) { - if ($hasParent && !$parentNeedsSVGContext) { - $contextArg = ", SVGElement*"; - } else { - $contextArg = ", SVGElement* context"; - } - } - push(@implContent, "${className}::$className(PassRefPtr<Structure> structure, PassRefPtr<$implType> impl$contextArg)\n"); + my $contextArg = $needsSVGContext ? ", SVGElement* context" : ""; + push(@implContent, "${className}::$className(PassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl$contextArg)\n"); if ($hasParent) { - push(@implContent, " : $parentClassName(structure, impl" . ($parentNeedsSVGContext ? ", context" : "") . ")\n"); + push(@implContent, " : $parentClassName(structure, globalObject, impl" . ($parentNeedsSVGContext ? ", context" : "") . ")\n"); } else { - push(@implContent, " : $parentClassName(structure)\n"); - push(@implContent, " , m_context(context)\n") if $needsSVGContext; - push(@implContent, " , m_impl(impl)\n"); + push(@implContent, " : $parentClassName(structure, globalObject" . ($needsSVGContext ? ", context" : "") . ")\n"); + push(@implContent, " , m_impl(impl)\n"); } } push(@implContent, "{\n"); @@ -1063,13 +1049,14 @@ sub GenerateImplementation || $dataNode->extendedAttributes->{"GenerateConstructor"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} + || $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"} || $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}; # Attributes if ($hasGetter) { - if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) { + if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) { push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n"); push(@implContent, "{\n"); push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0)); @@ -1107,6 +1094,7 @@ sub GenerateImplementation push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); push(@implContent, "{\n"); + push(@implContent, " ${className}* castedThis = static_cast<$className*>(asObject(slot.slotBase()));\n"); my $implClassNameForValueConversion = ""; if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) { @@ -1116,25 +1104,25 @@ sub GenerateImplementation if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) { - push(@implContent, " if (!static_cast<$className*>(asObject(slot.slotBase()))->allowsAccessFrom(exec))\n"); + push(@implContent, " if (!castedThis->allowsAccessFrom(exec))\n"); push(@implContent, " return jsUndefined();\n"); } if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"} || $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}) { - push(@implContent, " return static_cast<$className*>(asObject(slot.slotBase()))->$implGetterFunctionName(exec);\n"); + push(@implContent, " return castedThis->$implGetterFunctionName(exec);\n"); } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { $implIncludes{"JSDOMBinding.h"} = 1; - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n"); - push(@implContent, " return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "static_cast<$className*>(asObject(slot.slotBase()))") . " : jsUndefined();\n"); + push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); + push(@implContent, " return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n"); } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { $implIncludes{"Document.h"} = 1; $implIncludes{"JSDOMBinding.h"} = 1; - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n"); - push(@implContent, " return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "static_cast<$className*>(asObject(slot.slotBase()))") . " : jsUndefined();\n"); + push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); + push(@implContent, " return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "castedThis") . " : jsUndefined();\n"); } elsif ($type eq "EventListener") { $implIncludes{"EventListener.h"} = 1; push(@implContent, " UNUSED_PARAM(exec);\n"); - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n"); + push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); push(@implContent, " if (EventListener* listener = imp->$implGetterFunctionName()) {\n"); push(@implContent, " if (JSObject* jsFunction = listener->jsFunction())\n"); push(@implContent, " return jsFunction;\n"); @@ -1143,36 +1131,47 @@ sub GenerateImplementation } elsif ($attribute->signature->type =~ /Constructor$/) { my $constructorType = $codeGenerator->StripModule($attribute->signature->type); $constructorType =~ s/Constructor$//; - push(@implContent, " UNUSED_PARAM(slot);\n"); - push(@implContent, " return JS" . $constructorType . "::getConstructor(exec);\n"); + # Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object + # Once DOMObjects have a back-pointer to the globalObject we can pass castedThis->globalObject() + push(@implContent, " return JS" . $constructorType . "::getConstructor(exec, castedThis);\n"); } elsif (!@{$attribute->getterExceptions}) { push(@implContent, " UNUSED_PARAM(exec);\n"); if ($podType) { - push(@implContent, " $podType imp(*static_cast<$className*>(asObject(slot.slotBase()))->impl());\n"); + push(@implContent, " $podType imp(*castedThis->impl());\n"); if ($podType eq "float") { # Special case for JSSVGNumber - push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "static_cast<$className*>(asObject(slot.slotBase()))") . ";\n"); + push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n"); } else { - push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "static_cast<$className*>(asObject(slot.slotBase()))") . ";\n"); + push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n"); } } else { - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n"); - my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "static_cast<$className*>(asObject(slot.slotBase()))"); + push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); + my $value; + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + $implIncludes{"HTMLNames.h"} = 1; + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $name : ($reflect || $reflectURL); + my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; + $value = "imp->$getAttributeFunctionName(HTMLNames::${contentAttributeName}Attr)" + } else { + $value = "imp->$implGetterFunctionName()"; + } + my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, $value, "castedThis"); if ($codeGenerator->IsSVGAnimatedType($type)) { push(@implContent, " RefPtr<$type> obj = $jsType;\n"); - push(@implContent, " return toJS(exec, obj.get(), imp);\n"); + push(@implContent, " return toJS(exec, castedThis->globalObject(), obj.get(), imp);\n"); } else { push(@implContent, " return $jsType;\n"); } } } else { - push(@implContent, " ExceptionCode ec = 0;\n"); - + push(@implContent, " ExceptionCode ec = 0;\n"); if ($podType) { - push(@implContent, " $podType imp(*static_cast<$className*>(asObject(slot.slotBase()))->impl());\n"); - push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName(ec)", "static_cast<$className*>(asObject(slot.slotBase()))") . ";\n"); + push(@implContent, " $podType imp(*castedThis->impl());\n"); + push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n"); } else { - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n"); - push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName(ec)", "static_cast<$className*>(asObject(slot.slotBase()))") . ";\n"); + push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); + push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName(ec)", "castedThis") . ";\n"); } push(@implContent, " setDOMException(exec, ec);\n"); @@ -1193,7 +1192,15 @@ sub GenerateImplementation push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); push(@implContent, "{\n"); - push(@implContent, " return static_cast<$className*>(asObject(slot.slotBase()))->getConstructor(exec);\n"); + if (IsSVGTypeNeedingContextParameter($interfaceName)) { + # FIXME: SVG bindings with a context pointer have no space to store a globalObject + # so we use deprecatedGlobalObjectForPrototype instead. + push(@implContent, " UNUSED_PARAM(slot);\n"); + push(@implContent, " return ${className}::getConstructor(exec, deprecatedGlobalObjectForPrototype(exec));\n"); + } else { + push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); + push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); + } push(@implContent, "}\n"); } } @@ -1205,31 +1212,33 @@ sub GenerateImplementation } my $hasSetter = $hasReadWriteProperties - || $dataNode->extendedAttributes->{"CustomPutFunction"} + || $dataNode->extendedAttributes->{"DelegatingPutFunction"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}; if ($hasSetter) { - push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n"); - push(@implContent, "{\n"); - if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { - push(@implContent, " bool ok;\n"); - push(@implContent, " unsigned index = propertyName.toUInt32(&ok, false);\n"); - push(@implContent, " if (ok) {\n"); - push(@implContent, " indexSetter(exec, index, value);\n"); - push(@implContent, " return;\n"); - push(@implContent, " }\n"); - } - if ($dataNode->extendedAttributes->{"CustomPutFunction"}) { - push(@implContent, " if (customPut(exec, propertyName, value, slot))\n"); - push(@implContent, " return;\n"); - } + if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) { + push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n"); + push(@implContent, "{\n"); + if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { + push(@implContent, " bool ok;\n"); + push(@implContent, " unsigned index = propertyName.toUInt32(&ok, false);\n"); + push(@implContent, " if (ok) {\n"); + push(@implContent, " indexSetter(exec, index, value);\n"); + push(@implContent, " return;\n"); + push(@implContent, " }\n"); + } + if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) { + push(@implContent, " if (putDelegate(exec, propertyName, value, slot))\n"); + push(@implContent, " return;\n"); + } - if ($hasReadWriteProperties) { - push(@implContent, " lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n"); - } else { - push(@implContent, " Base::put(exec, propertyName, value, slot);\n"); + if ($hasReadWriteProperties) { + push(@implContent, " lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n"); + } else { + push(@implContent, " Base::put(exec, propertyName, value, slot);\n"); + } + push(@implContent, "}\n\n"); } - push(@implContent, "}\n\n"); if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) { push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue value)\n"); @@ -1295,8 +1304,17 @@ sub GenerateImplementation push(@implContent, " static_cast<$className*>(thisObject)->impl()->commitChange(imp, static_cast<$className*>(thisObject)->context());\n"); } else { push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); + my $nativeValue = JSValueToNative($attribute->signature, "value"); push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; - push(@implContent, " imp->set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value")); + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + $implIncludes{"HTMLNames.h"} = 1; + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $name : ($reflect || $reflectURL); + push(@implContent, " imp->setAttribute(HTMLNames::${contentAttributeName}Attr, $nativeValue"); + } else { + push(@implContent, " imp->set$implSetterFunctionName($nativeValue"); + } push(@implContent, ", ec") if @{$attribute->setterExceptions}; push(@implContent, ");\n"); push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; @@ -1315,13 +1333,9 @@ sub GenerateImplementation } } - if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) { + if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) { push(@implContent, "void ${className}::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n"); push(@implContent, "{\n"); - if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"}) { - push(@implContent, " if (customGetPropertyNames(exec, propertyNames))\n"); - push(@implContent, " return;\n"); - } if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) { push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n"); push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n"); @@ -1331,8 +1345,8 @@ sub GenerateImplementation } if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { - push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec)\n{\n"); - push(@implContent, " return getDOMConstructor<${className}Constructor>(exec);\n"); + push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n"); + push(@implContent, " return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n"); push(@implContent, "}\n\n"); } @@ -1348,12 +1362,16 @@ sub GenerateImplementation push(@implContent, "{\n"); push(@implContent, " UNUSED_PARAM(args);\n"); - $implKJSInclude{"Error.h"} = 1; + $implIncludes{"<runtime/Error.h>"} = 1; if ($interfaceName eq "DOMWindow") { push(@implContent, " $className* castedThisObj = toJSDOMWindow(thisValue.toThisObject(exec));\n"); push(@implContent, " if (!castedThisObj)\n"); push(@implContent, " return throwError(exec, TypeError);\n"); + } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { + push(@implContent, " $className* castedThisObj = to${className}(thisValue.toThisObject(exec));\n"); + push(@implContent, " if (!castedThisObj)\n"); + push(@implContent, " return throwError(exec, TypeError);\n"); } else { push(@implContent, " if (!thisValue.isObject(&${className}::s_info))\n"); push(@implContent, " return throwError(exec, TypeError);\n"); @@ -1481,7 +1499,7 @@ sub GenerateImplementation $implIncludes{"KURL.h"} = 1; push(@implContent, " return jsStringOrNull(exec, thisObj->impl()->item(slot.index()));\n"); } else { - push(@implContent, " return toJS(exec, static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n"); + push(@implContent, " return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n"); } push(@implContent, "}\n"); if ($interfaceName eq "HTMLCollection") { @@ -1490,22 +1508,22 @@ sub GenerateImplementation } } - if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !UsesManualToJSImplementation($implClassName)) { + if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) { if ($podType) { - push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n"); + push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n"); } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, $implType* object, SVGElement* context)\n"); + push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n"); } else { - push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, $implType* object)\n"); + push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n"); } push(@implContent, "{\n"); if ($podType) { - push(@implContent, " return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, object, context);\n"); + push(@implContent, " return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, globalObject, object, context);\n"); } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@implContent, " return getDOMObjectWrapper<$className>(exec, object, context);\n"); + push(@implContent, " return getDOMObjectWrapper<$className>(exec, globalObject, object, context);\n"); } else { - push(@implContent, " return getDOMObjectWrapper<$className>(exec, object);\n"); + push(@implContent, " return getDOMObjectWrapper<$className>(exec, globalObject, object);\n"); } push(@implContent, "}\n"); } @@ -1664,7 +1682,7 @@ sub NativeToJSValue return "jsBoolean($value)" if $type eq "boolean"; if ($codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp") { - $implKJSInclude{"JSNumberCell.h"} = 1; + $implIncludes{"<runtime/JSNumberCell.h>"} = 1; return "jsNumber(exec, $value)"; } @@ -1678,14 +1696,12 @@ sub NativeToJSValue die "Unknown value for ConvertNullStringTo extended attribute"; } - $implKJSInclude{"JSString.h"} = 1; + $implIncludes{"<runtime/JSString.h>"} = 1; return "jsString(exec, $value)"; } - - if ($type eq "RGBColor") { - $implIncludes{"JS$type.h"} = 1; - return "getJSRGBColor(exec, $value)"; - } + + # Some SVG bindings don't have space to store a globalObject pointer, for those, we use the deprecatedGlobalObjectForPrototype hack for now. + my $globalObject = IsSVGTypeNeedingContextParameter($implClassName) ? "deprecatedGlobalObjectForPrototype(exec)" : "$thisValue->globalObject()"; if ($codeGenerator->IsPodType($type)) { $implIncludes{"JS$type.h"} = 1; @@ -1704,24 +1720,25 @@ sub NativeToJSValue and $codeGenerator->IsPodTypeWithWriteableProperties($type) and not defined $signature->extendedAttributes->{"Immutable"}) { if ($codeGenerator->IsPodType($implClassName)) { - return "toJS(exec, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), $thisValue->context())"; + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), $thisValue->context())"; } else { - return "toJS(exec, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)"; + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)"; } } if ($implClassNameForValueConversion eq "") { - if (IsSVGTypeNeedingContextParameter($implClassName)) { - return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), castedThisObj->context())" if $inFunctionCall eq 1; + # SVGZoomEvent has no context() pointer, and is also not an SVGElement. + # This is not a problem, because SVGZoomEvent has no read/write properties. + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0)" if $implClassName eq "SVGZoomEvent"; - # Special case: SVGZoomEvent - it doesn't have a context, but it's no problem, as there are no readwrite props - return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0)" if $implClassName eq "SVGZoomEvent"; - return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), $thisValue->context())"; + if (IsSVGTypeNeedingContextParameter($implClassName)) { + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), castedThisObj->context())" if $inFunctionCall; + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), $thisValue->context())"; } else { - return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), imp)"; + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), imp)"; } } else { # These classes, always have a m_context pointer! - return "toJS(exec, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), $thisValue->context())"; + return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), $thisValue->context())"; } } @@ -1754,18 +1771,15 @@ sub NativeToJSValue return $value if $codeGenerator->IsSVGAnimatedType($type); if (IsSVGTypeNeedingContextParameter($type)) { - if (IsSVGTypeNeedingContextParameter($implClassName)) { - return "toJS(exec, WTF::getPtr($value), $thisValue->context())"; - } else { - return "toJS(exec, WTF::getPtr($value), imp)"; - } + my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "$thisValue->context()" : "imp"; + return "toJS(exec, $globalObject, WTF::getPtr($value), $contextPtr)"; } if ($signature->extendedAttributes->{"ReturnsNew"}) { - return "toJSNewlyCreated(exec, WTF::getPtr($value))"; + return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))"; } - return "toJS(exec, WTF::getPtr($value))"; + return "toJS(exec, $globalObject, WTF::getPtr($value))"; } sub ceilingToPowerOf2 @@ -1895,7 +1909,7 @@ tableSizeLoop: push(@implContent, "};\n\n"); my $perfectSizeMask = $perfectSize - 1; my $compactSizeMask = $numEntries - 1; - push(@implContent, "static const HashTable $name =\n"); + push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name =\n"); push(@implContent, "#if ENABLE(PERFECT_HASH_SIZE)\n"); push(@implContent, " { $perfectSizeMask, $nameEntries, 0 };\n"); push(@implContent, "#else\n"); @@ -1964,17 +1978,17 @@ sub WriteData # Write content to file. print $IMPL @implContentHeader; - foreach my $implInclude (sort keys(%implIncludes)) { - my $checkType = $implInclude; + my @includes = (); + foreach my $include (keys %implIncludes) { + my $checkType = $include; $checkType =~ s/\.h//; + next if $codeGenerator->IsSVGAnimatedType($checkType); - print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType); + $include = "\"$include\"" unless $include =~ /^["<]/; # " + push @includes, $include; } - - print $IMPL "\n"; - - foreach my $implKJSInclude (sort keys(%implKJSInclude)) { - print $IMPL "#include <runtime/$implKJSInclude>\n"; + foreach my $include (sort @includes) { + print $IMPL "#include $include\n"; } print $IMPL @implContent; @@ -1984,15 +1998,19 @@ sub WriteData @implContentHeader = (); @implContent = (); %implIncludes = (); - %implKJSIncludes = (); } if (defined($HEADER)) { # Write content to file. print $HEADER @headerContentHeader; - foreach my $headerInclude (sort keys(%headerIncludes)) { - print $HEADER "#include \"$headerInclude\"\n"; + my @includes = (); + foreach my $include (keys %headerIncludes) { + $include = "\"$include\"" unless $include =~ /^["<]/; # " + push @includes, $include; + } + foreach my $include (sort @includes) { + print $HEADER "#include $include\n"; } print $HEADER @headerContent; @@ -2012,14 +2030,15 @@ sub constructorFor my $interfaceName = shift; my $visibleClassName = shift; my $canConstruct = shift; + my $constructorClassName = "${className}Constructor"; my $implContent = << "EOF"; -class ${className}Constructor : public DOMObject { +class ${constructorClassName} : public DOMConstructorObject { public: - ${className}Constructor(ExecState* exec) - : DOMObject(${className}Constructor::createStructure(exec->lexicalGlobalObject()->objectPrototype())) + ${constructorClassName}(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(${constructorClassName}::createStructure(globalObject->objectPrototype()), globalObject) { - putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec, exec->lexicalGlobalObject()), None); + putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), None); } virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual const ClassInfo* classInfo() const { return &s_info; } @@ -2033,13 +2052,13 @@ EOF if ($canConstruct) { $implContent .= << "EOF"; - static JSObject* construct(ExecState* exec, JSObject*, const ArgList&) + static JSObject* construct${interfaceName}(ExecState* exec, JSObject* constructor, const ArgList&) { - return asObject(toJS(exec, ${interfaceName}::create())); + return asObject(toJS(exec, static_cast<${constructorClassName}*>(constructor)->globalObject(), ${interfaceName}::create())); } virtual ConstructType getConstructData(ConstructData& constructData) { - constructData.native.function = construct; + constructData.native.function = construct${interfaceName}; return ConstructTypeHost; } EOF @@ -2048,16 +2067,16 @@ EOF $implContent .= << "EOF"; }; -const ClassInfo ${className}Constructor::s_info = { "${visibleClassName}Constructor", 0, &${className}ConstructorTable, 0 }; +const ClassInfo ${constructorClassName}::s_info = { "${visibleClassName}Constructor", 0, &${constructorClassName}Table, 0 }; -bool ${className}Constructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - return getStaticValueSlot<${className}Constructor, DOMObject>(exec, &${className}ConstructorTable, this, propertyName, slot); + return getStaticValueSlot<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, slot); } EOF - $implKJSInclude{"JSNumberCell.h"} = 1; + $implJSCInclude{"JSNumberCell.h"} = 1; # FIXME: What is this for? return $implContent; } diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm index fc265f9..f449e19 100644 --- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm +++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm @@ -515,15 +515,17 @@ sub AddIncludesForType { my $type = $codeGenerator->StripModule(shift); - return if $codeGenerator->IsNonPointerType($type) or IsNativeObjCType($type); + return if $codeGenerator->IsNonPointerType($type); - if ($codeGenerator->IsStringType($type)) { - $implIncludes{"KURL.h"} = 1; + if (IsNativeObjCType($type)) { + if ($type eq "Color") { + $implIncludes{"ColorMac.h"} = 1; + } return; } - if ($type eq "RGBColor") { - $implIncludes{"DOMRGBColorInternal.h"} = 1; + if ($codeGenerator->IsStringType($type)) { + $implIncludes{"KURL.h"} = 1; return; } @@ -924,8 +926,6 @@ sub GenerateHeader if ($codeGenerator->IsSVGAnimatedType($interfaceName)) { push(@internalHeaderContent, "#import <WebCore/SVGAnimatedTemplate.h>\n\n"); - } elsif ($interfaceName eq "RGBColor") { - push(@internalHeaderContent, "#import <WebCore/Color.h>\n\n"); } else { push(@internalHeaderContent, "namespace WebCore {\n"); $startedNamespace = 1; @@ -1059,9 +1059,12 @@ sub GenerateImplementation # Only generate 'dealloc' and 'finalize' methods for direct subclasses of DOMObject. if ($parentImplClassName eq "Object") { + $implIncludes{"WebCoreObjCExtras.h"} = 1; push(@implContent, "- (void)dealloc\n"); push(@implContent, "{\n"); - push(@implContent, " $assertMainThread\n"); + push(@implContent, " if (WebCoreObjCScheduleDeallocateOnMainThread([$className class], self))\n"); + push(@implContent, " return;\n"); + push(@implContent, "\n"); if ($interfaceName eq "NodeIterator") { push(@implContent, " if (_internal) {\n"); push(@implContent, " [self detach];\n"); @@ -1129,7 +1132,17 @@ sub GenerateImplementation # - GETTER my $getterSig = "- ($attributeType)$attributeInterfaceName\n"; my $hasGetterException = @{$attribute->getterExceptions}; - my $getterContentHead = "IMPL->" . $codeGenerator->WK_lcfirst($attributeName) . "("; + my $getterContentHead; + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + $implIncludes{"HTMLNames.h"} = 1; + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); + my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; + $getterContentHead = "IMPL->${getAttributeFunctionName}(WebCore::HTMLNames::${contentAttributeName}Attr"; + } else { + $getterContentHead = "IMPL->" . $codeGenerator->WK_lcfirst($attributeName) . "("; + } my $getterContentTail = ")"; # Special case for DOMSVGNumber @@ -1188,6 +1201,9 @@ sub GenerateImplementation } elsif (IsProtocolType($idlType) and $idlType ne "EventTarget") { $getterContentHead = "kit($getterContentHead"; $getterContentTail .= ")"; + } elsif ($idlType eq "Color") { + $getterContentHead = "WebCore::nsColor($getterContentHead"; + $getterContentTail .= ")"; } elsif (ConversionNeeded($attribute->signature->type)) { $getterContentHead = "kit(WTF::getPtr($getterContentHead"; $getterContentTail .= "))"; @@ -1226,7 +1242,7 @@ sub GenerateImplementation # Exception handling my $hasSetterException = @{$attribute->setterExceptions}; - $attributeName = "set" . $codeGenerator->WK_ucfirst($attributeName); + my $coreSetterName = "set" . $codeGenerator->WK_ucfirst($attributeName); my $setterName = "set" . ucfirst($attributeInterfaceName); my $argName = "new" . ucfirst($attributeInterfaceName); my $arg = GetObjCTypeGetter($argName, $idlType); @@ -1252,14 +1268,22 @@ sub GenerateImplementation if ($podType eq "float") { push(@implContent, " *IMPL = $arg;\n"); } else { - push(@implContent, " IMPL->$attributeName($arg);\n"); + push(@implContent, " IMPL->$coreSetterName($arg);\n"); } } elsif ($hasSetterException) { push(@implContent, " $exceptionInit\n"); - push(@implContent, " IMPL->$attributeName($arg, ec);\n"); + push(@implContent, " IMPL->$coreSetterName($arg, ec);\n"); push(@implContent, " $exceptionRaiseOnError\n"); } else { - push(@implContent, " IMPL->$attributeName($arg);\n"); + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + $implIncludes{"HTMLNames.h"} = 1; + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); + push(@implContent, " IMPL->setAttribute(WebCore::HTMLNames::${contentAttributeName}Attr, $arg);\n"); + } else { + push(@implContent, " IMPL->$coreSetterName($arg);\n"); + } } push(@implContent, "}\n\n"); diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm new file mode 100644 index 0000000..f696e9f --- /dev/null +++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -0,0 +1,2228 @@ + +# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> +# Copyright (C) 2006 Anders Carlsson <andersca@mac.com> +# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> +# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> +# Copyright (C) 2006 Apple Computer, Inc. +# Copyright (C) 2007, 2008, 2009 Google Inc. +# +# This file is part of the KDE project +# +# 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 +# aint with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +package CodeGeneratorV8; + +use File::stat; +use Digest::MD5; + +my $module = ""; +my $outputDir = ""; + +my @headerContent = (); +my @implContentHeader = (); +my @implFixedHeader = (); +my @implContent = (); +my @implContentDecls = (); +my %implIncludes = (); + +my @allParents = (); + +# Default .h template +my $headerTemplate = << "EOF"; +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +EOF + +# Default constructor +sub new +{ + my $object = shift; + my $reference = { }; + + $codeGenerator = shift; + $outputDir = shift; + + bless($reference, $object); + return $reference; +} + +sub finish +{ + my $object = shift; + + # Commit changes! + $object->WriteData(); +} + +sub leftShift($$) { + my ($value, $distance) = @_; + return (($value << $distance) & 0xFFFFFFFF); +} + +# Uppercase the first letter, while respecting WebKit style guidelines. +# E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang. +sub WK_ucfirst +{ + my $param = shift; + my $ret = ucfirst($param); + $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/; + return $ret; +} + +# Lowercase the first letter while respecting WebKit style guidelines. +# URL becomes url, but SetURL becomes setURL. +sub WK_lcfirst +{ + my $param = shift; + my $ret = lcfirst($param); + $ret =~ s/uRL/url/; + return $ret; +} + +# Workaround for V8 bindings difference where RGBColor is not a POD type. +sub IsPodType +{ + my $type = shift; + return $codeGenerator->IsPodType($type); +} + +# Params: 'domClass' struct +sub GenerateInterface +{ + my $object = shift; + my $dataNode = shift; + my $defines = shift; + + # Start actual generation + $object->GenerateHeader($dataNode); + $object->GenerateImplementation($dataNode); + + my $name = $dataNode->name; + + # Open files for writing + my $headerFileName = "$outputDir/V8$name.h"; + my $implFileName = "$outputDir/V8$name.cpp"; + + open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName"; + open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName"; +} + +# Params: 'idlDocument' struct +sub GenerateModule +{ + my $object = shift; + my $dataNode = shift; + + $module = $dataNode->module; +} + +sub GetLegacyHeaderIncludes +{ + my $legacyParent = shift; + + die "Don't know what headers to include for module $module"; +} + +sub AvoidInclusionOfType +{ + my $type = shift; + + # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist. + return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix"; + return 0; +} + +sub UsesManualToJSImplementation +{ + my $type = shift; + + return 1 if $type eq "SVGPathSeg"; + return 0; +} + +sub AddIncludesForType +{ + my $type = $codeGenerator->StripModule(shift); + + # When we're finished with the one-file-per-class + # reorganization, we won't need these special cases. + if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type)) { + } elsif ($type =~ /SVGPathSeg/) { + $joinedName = $type; + $joinedName =~ s/Abs|Rel//; + $implIncludes{"${joinedName}.h"} = 1; + } else { + # default, include the same named file + $implIncludes{GetImplementationFileName(${type})} = 1; + } + + # additional includes (things needed to compile the bindings but not the header) + + if ($type eq "CanvasRenderingContext2D") { + $implIncludes{"CanvasGradient.h"} = 1; + $implIncludes{"CanvasPattern.h"} = 1; + $implIncludes{"CanvasStyle.h"} = 1; + } + + if ($type eq "CanvasGradient" or $type eq "XPathNSResolver") { + $implIncludes{"PlatformString.h"} = 1; + } + + if ($type eq "CSSStyleDeclaration") { + $implIncludes{"CSSMutableStyleDeclaration.h"} = 1; + } + + if ($type eq "Plugin" or $type eq "PluginArray" or $type eq "MimeTypeArray") { + # So we can get String -> AtomicString conversion for namedItem(). + $implIncludes{"AtomicString.h"} = 1; + } +} + +sub AddIncludesForSVGAnimatedType +{ + my $type = shift; + $type =~ s/SVGAnimated//; + + if ($type eq "Point" or $type eq "Rect") { + $implIncludes{"Float$type.h"} = 1; + } elsif ($type eq "String") { + $implIncludes{"PlatformString.h"} = 1; + } + + $implIncludes{"SVGAnimatedTemplate.h"} = 1; +} + +sub AddClassForwardIfNeeded +{ + my $implClassName = shift; + + # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them! + push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName); +} + +sub GetImplementationFileName +{ + my $iface = shift; + return "HTMLCollection.h" if $iface eq "HTMLAllCollection"; + return "Event.h" if $iface eq "DOMTimeStamp"; + return "NamedAttrMap.h" if $iface eq "NamedNodeMap"; + return "NameNodeList.h" if $iface eq "NodeList"; + return "XMLHttpRequest.h" if $iface eq "XMLHttpRequest"; + + return "${iface}.h"; +} + +# If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if. +sub GenerateConditionalString +{ + my $node = shift; + my $conditional = $node->extendedAttributes->{"Conditional"}; + if ($conditional) { + return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + } else { + return ""; + } +} + +sub GenerateHeader +{ + my $object = shift; + my $dataNode = shift; + + my $interfaceName = $dataNode->name; + my $className = "V8$interfaceName"; + my $implClassName = $interfaceName; + + # Copy contents of parent classes except the first parent or if it is + # EventTarget. + $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode); + + my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; + my $conditionalString = GenerateConditionalString($dataNode); + + # - Add default header template + @headerContent = split("\r", $headerTemplate); + + push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString; + push(@headerContent, "\n#ifndef $className" . "_H"); + push(@headerContent, "\n#define $className" . "_H\n\n"); + + # Get correct pass/store types respecting PODType flag + my $podType = $dataNode->extendedAttributes->{"PODType"}; + my $passType = $podType ? "JSSVGPODTypeWrapper<$podType>*" : "$implClassName*"; + + push(@headerContent, "#include \"$podType.h\"\n") if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32"); + + push(@headerContent, "#include <v8.h>\n"); + push(@headerContent, "#include <wtf/HashMap.h>\n"); + push(@headerContent, "#include \"StringHash.h\"\n"); + + push(@headerContent, "\nnamespace WebCore {\n\n"); + push(@headerContent, "class V8ClassIndex;\n"); + push(@headerContent, "\nclass $className {\n"); + push(@headerContent, <<END); + + public: + static bool HasInstance(v8::Handle<v8::Value> value); + static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); +END + + if ($implClassName eq "DOMWindow") { + push(@headerContent, <<END); + static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate(); +END + } + + push(@headerContent, <<END); + + private: + static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + + friend class V8ClassIndex; +}; + +END + + push(@headerContent, "}\n\n"); + push(@headerContent, "#endif // $className" . "_H\n"); + + push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; +} + + +sub GenerateSetDOMException +{ + my $indent = shift; + my $result = ""; + + $result .= $indent . "if (ec) {\n"; + $result .= $indent . " V8Proxy::setDOMException(ec);\n"; + $result .= $indent . " return v8::Handle<v8::Value>();\n"; + $result .= $indent . "}\n"; + + return $result; +} + +sub IsNodeSubType +{ + my $dataNode = shift; + return 1 if ($dataNode->name eq "Node"); + foreach (@allParents) { + my $parent = $codeGenerator->StripModule($_); + return 1 if $parent eq "Node"; + } + return 0; +} + +sub HolderToNative +{ + my $dataNode = shift; + my $implClassName = shift; + my $classIndex = shift; + + if (IsNodeSubType($dataNode)) { + push(@implContentDecls, <<END); + $implClassName* imp = V8DOMWrapper::convertDOMWrapperToNode<$implClassName>(holder); +END + + } else { + push(@implContentDecls, <<END); + $implClassName* imp = V8DOMWrapper::convertToNativeObject<$implClassName>(V8ClassIndex::$classIndex, holder); +END + + } +} + +sub GenerateDomainSafeFunctionGetter +{ + my $function = shift; + my $dataNode = shift; + my $classIndex = shift; + my $implClassName = shift; + + my $className = "V8" . $dataNode->name; + my $funcName = $function->signature->name; + + my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())"; + if ($function->signature->extendedAttributes->{"V8DoNotCheckSignature"}) { + $signature = "v8::Local<v8::Signature>()"; + } + + my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature); + + $implIncludes{"V8Proxy.h"} = 1; + + push(@implContentDecls, <<END); + static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { + INC_STATS(\"DOM.$implClassName.$funcName._get\"); + static v8::Persistent<v8::FunctionTemplate> private_template = + v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This()); + if (holder.IsEmpty()) { + // can only reach here by 'object.__proto__.func', and it should passed + // domain security check already + + return private_template->GetFunction(); + } +END + + HolderToNative($dataNode, $implClassName, $classIndex); + + push(@implContentDecls, <<END); + if (!V8Proxy::canAccessFrame(imp->frame(), false)) { + static v8::Persistent<v8::FunctionTemplate> shared_template = + v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); + return shared_template->GetFunction(); + + } else { + return private_template->GetFunction(); + } + } + +END +} + +sub GenerateConstructorGetter +{ + my $implClassName = shift; + my $classIndex = shift; + + push(@implContentDecls, <<END); + static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { + INC_STATS(\"DOM.$implClassName.constructors._get\"); + v8::Handle<v8::Value> data = info.Data(); + ASSERT(data->IsNumber()); + V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(data->Int32Value()); +END + + if ($classIndex eq "DOMWINDOW") { + push(@implContentDecls, <<END); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + // Get the proxy corresponding to the DOMWindow if possible to + // make sure that the constructor function is constructed in the + // context of the DOMWindow and not in the context of the caller. + return V8DOMWrapper::getConstructor(type, window); +END + } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") { + $implIncludes{"WorkerContextExecutionProxy.h"} = 1; + push(@implContentDecls, <<END); + WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); + return V8DOMWrapper::getConstructor(type, workerContext); +END + } else { + push(@implContentDecls, " return v8::Undefined();"); + } + + push(@implContentDecls, <<END); + + } + +END +} + +sub GenerateNormalAttrGetter +{ + my $attribute = shift; + my $dataNode = shift; + my $classIndex = shift; + my $implClassName = shift; + + my $attrExt = $attribute->signature->extendedAttributes; + + my $attrName = $attribute->signature->name; + $implIncludes{"V8Proxy.h"} = 1; + + my $attrType = GetTypeFromSignature($attribute->signature); + my $attrIsPodType = IsPodType($attrType); + + my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0); + my $isPodType = IsPodType($implClassName); + my $skipContext = 0; + + + if ($isPodType) { + $implClassName = GetNativeType($implClassName); + $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; + } + + # Special case: SVGZoomEvent's attributes are all read-only + if ($implClassName eq "SVGZoomEvent") { + $attrIsPodType = 0; + $skipContext = 1; + } + + # Special case: SVGSVGEelement::viewport is read-only + if (($implClassName eq "SVGSVGElement") and ($attrName eq "viewport")) { + $attrIsPodType = 0; + $skipContext = 1; + } + + # Special case for SVGColor + if (($implClassName eq "SVGColor") and ($attrName eq "rgbColor")) { + $attrIsPodType = 0; + } + + my $getterStringUsesImp = $implClassName ne "double"; + + # Getter + push(@implContentDecls, <<END); + static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { + INC_STATS(\"DOM.$implClassName.$attrName._get\"); +END + + if ($isPodType) { + push(@implContentDecls, <<END); + V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder()); + $implClassName imp_instance = *imp_wrapper; +END + if ($getterStringUsesImp) { + push(@implContentDecls, <<END); + $implClassName* imp = &imp_instance; +END + } + + } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) { + # perform lookup first + push(@implContentDecls, <<END); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This()); + if (holder.IsEmpty()) return v8::Undefined(); +END + HolderToNative($dataNode, $implClassName, $classIndex); + } else { + push(@implContentDecls, <<END); + v8::Handle<v8::Object> holder = info.Holder(); +END + HolderToNative($dataNode, $implClassName, $classIndex); + } + + # Generate security checks if necessary + if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { + push(@implContentDecls, " if (!V8Proxy::checkNodeSecurity(imp->$attrName())) return v8::Undefined();\n\n"); + } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { + push(@implContentDecls, " if (!V8Proxy::checkNodeSecurity(imp->contentDocument())) return v8::Undefined();\n\n"); + } + + my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType); + if ($useExceptions) { + $implIncludes{"ExceptionCode.h"} = 1; + push(@implContentDecls, " ExceptionCode ec = 0;\n"); + } + + if ($attribute->signature->extendedAttributes->{"v8referenceattr"}) { + $attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"}; + } + + my $getterFunc = WK_lcfirst($attrName); + $getterFunc .= "Animated" if $codeGenerator->IsSVGAnimatedType($attribute->signature->type); + + my $returnType = GetTypeFromSignature($attribute->signature); + + my $getterString; + if ($getterStringUsesImp) { + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + $implIncludes{"HTMLNames.h"} = 1; + my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL); + my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; + $getterString = "imp->$getAttributeFunctionName(HTMLNames::${contentAttributeName}Attr"; + } else { + $getterString = "imp->$getterFunc("; + } + $getterString .= "ec" if $useExceptions; + $getterString .= ")"; + if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) { + $getterString .= ".toInt()"; + } + } else { + $getterString = "imp_instance"; + } + + if ($nativeType eq "String") { + $getterString = "toString($getterString)"; + } + + my $result; + my $wrapper; + + if ($attrIsPodType) { + $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; + + my $getter = $getterString; + $getter =~ s/imp->//; + $getter =~ s/\(\)//; + my $setter = "set" . WK_ucfirst($getter); + + my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName); + if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) { + if (IsPodType($implClassName)) { + my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)"; + push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n"); + } else { + my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)"; + push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName> > wrapper = $wrapper;\n"); + } + } else { + if ($implClassIsAnimatedType) { + # We can't hash member function pointers, so instead generate + # some hashing material based on the names of the methods. + my $hashhex = substr(Digest::MD5::md5_hex("${implClassName}::$getter ${implClassName}::$setter)"), 0, 8); + my $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter, 0x$hashhex)"; + push(@implContentDecls, " RefPtr<V8SVGPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n"); + } else { + my $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString); + push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapper<" . $nativeType . "> > wrapper = $wrapper;\n"); + } + } + + } else { + push(@implContentDecls, " $nativeType v = "); + + push(@implContentDecls, "$getterString;\n"); + + if ($useExceptions) { + push(@implContentDecls, GenerateSetDOMException(" ")); + } + + $result = "v"; + } + + if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) { + my $resultObject = $result; + if ($attrIsPodType) { + $resultObject = "wrapper"; + } + $resultObject = "WTF::getPtr(" . $resultObject . ")"; + push(@implContentDecls, GenerateSVGContextAssignment($implClassName, $resultObject, " ")); + } + + if ($attrIsPodType) { + my $classIndex = uc($attrType); + push(@implContentDecls, " return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n"); + } else { + $result .= ".release()" if (IsRefPtrType($attrType)); + push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n"); + } + + push(@implContentDecls, " }\n\n"); # end of getter +} + + +sub GenerateReplaceableAttrSetter +{ + my $implClassName = shift; + + $implIncludes{"V8Proxy.h"} = 1; + + push(@implContentDecls, + " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . + " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); + + push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n"); + + push(@implContentDecls, " v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n"); + push(@implContentDecls, " info.Holder()->Delete(${attrName}_string);\n"); + push(@implContentDecls, " info.This()->Set(${attrName}_string, value);\n"); + push(@implContentDecls, " }\n\n"); +} + + +sub GenerateNormalAttrSetter +{ + my $attribute = shift; + my $dataNode = shift; + my $classIndex = shift; + my $implClassName = shift; + + my $attrExt = $attribute->signature->extendedAttributes; + + $implIncludes{"V8Proxy.h"} = 1; + + push(@implContentDecls, + " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . + " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); + + push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n"); + + my $isPodType = IsPodType($implClassName); + + if ($isPodType) { + $implClassName = GetNativeType($implClassName); + $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; + push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n"); + push(@implContentDecls, " $implClassName imp_instance = *wrapper;\n"); + push(@implContentDecls, " $implClassName* imp = &imp_instance;\n"); + + } elsif ($attrExt->{"v8OnProto"}) { + # perform lookup first + push(@implContentDecls, <<END); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This()); + if (holder.IsEmpty()) return v8::Undefined(); +END + HolderToNative($dataNode, $implClassName, $classIndex); + } else { + push(@implContentDecls, <<END); + v8::Handle<v8::Object> holder = info.Holder(); +END + HolderToNative($dataNode, $implClassName, $classIndex); + } + + my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0); + push(@implContentDecls, " $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n"); + + my $result = ""; + if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) { + $result .= "WebCore::String::number("; + } + $result .= "v"; + if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) { + $result .= ")"; + } + my $returnType = GetTypeFromSignature($attribute->signature); + if (IsRefPtrType($returnType)) { + $result = "WTF::getPtr(" . $result . ")"; + } + + my $useExceptions = 1 if @{$attribute->setterExceptions} and !($isPodType); + + if ($useExceptions) { + $implIncludes{"ExceptionCode.h"} = 1; + push(@implContentDecls, " ExceptionCode ec = 0;\n"); + } + + if ($implClassName eq "double") { + push(@implContentDecls, " *imp = $result;\n"); + } else { + my $implSetterFunctionName = WK_ucfirst($attrName); + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + $implIncludes{"HTMLNames.h"} = 1; + my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL); + push(@implContentDecls, " imp->setAttribute(HTMLNames::${contentAttributeName}Attr, $result"); + } else { + push(@implContentDecls, " imp->set$implSetterFunctionName(" . $result); + } + push(@implContentDecls, ", ec") if $useExceptions; + push(@implContentDecls, ");\n"); + } + + if ($useExceptions) { + push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); + } + + if ($isPodType) { + push(@implContentDecls, " wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n"); + } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { + $implIncludes{"SVGElement.h"} = 1; + + my $currentObject = "imp"; + if ($isPodType) { + $currentObject = "wrapper"; + } + + push(@implContentDecls, " if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n"); + push(@implContentDecls, " context->svgAttributeChanged(imp->associatedAttributeName());\n"); + push(@implContentDecls, " }\n"); + } + + push(@implContentDecls, " return;\n"); + push(@implContentDecls, " }\n\n"); # end of setter +} + +sub GenerateNewFunctionTemplate +{ + $function = shift; + $dataNode = shift; + $signature = shift; + + my $interfaceName = $dataNode->name; + my $name = $function->signature->name; + + if ($function->signature->extendedAttributes->{"Custom"} || + $function->signature->extendedAttributes->{"V8Custom"}) { + if ($function->signature->extendedAttributes->{"Custom"} && + $function->signature->extendedAttributes->{"V8Custom"}) { + die "Custom and V8Custom should be mutually exclusive!" + } + my $customFunc = $function->signature->extendedAttributes->{"Custom"} || + $function->signature->extendedAttributes->{"V8Custom"}; + if ($customFunc eq 1) { + $customFunc = $interfaceName . WK_ucfirst($name); + } + return "v8::FunctionTemplate::New(V8Custom::v8${customFunc}Callback, v8::Handle<v8::Value>(), $signature)"; + } else { + return "v8::FunctionTemplate::New(${interfaceName}Internal::${name}Callback, v8::Handle<v8::Value>(), $signature)"; + } +} + +sub GenerateFunctionCallback +{ + my $function = shift; + my $dataNode = shift; + my $classIndex = shift; + my $implClassName = shift; + + my $interfaceName = $dataNode->name; + my $name = $function->signature->name; + + push(@implContentDecls, +" static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" . +" INC_STATS(\"DOM.$implClassName.$name\");\n"); + + my $numParameters = @{$function->parameters}; + + if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) { + push(@implContentDecls, + " if (args.Length() < $numParameters) return v8::Undefined();\n"); + } + + if (IsPodType($implClassName)) { + my $nativeClassName = GetNativeType($implClassName); + push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n"); + push(@implContentDecls, " $nativeClassName imp_instance = *imp_wrapper;\n"); + push(@implContentDecls, " $nativeClassName* imp = &imp_instance;\n"); + } else { + push(@implContentDecls, <<END); + v8::Handle<v8::Object> holder = args.Holder(); +END + HolderToNative($dataNode, $implClassName, $classIndex); + } + + # Check domain security if needed + if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} + || $interfaceName eq "DOMWindow") + && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { + # We have not find real use cases yet. + push(@implContentDecls, +" if (!V8Proxy::canAccessFrame(imp->frame(), true)) {\n". +" return v8::Undefined();\n" . +" }\n"); + } + + + if (@{$function->raisesExceptions}) { + $implIncludes{"ExceptionCode.h"} = 1; + push(@implContentDecls, " ExceptionCode ec = 0;\n"); + } + + if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { + push(@implContentDecls, " ScriptCallStack callStack(args, $numParameters);\n"); + $implIncludes{"ScriptCallStack.h"} = 1; + } + + my $paramIndex = 0; + foreach my $parameter (@{$function->parameters}) { + TranslateParameter($parameter); + + my $parameterName = $parameter->name; + + if ($parameter->extendedAttributes->{"Optional"}) { + # Generate early call if there are not enough parameters. + push(@implContentDecls, " if (args.Length() <= $paramIndex) {\n"); + my $functionCall = GenerateFunctionCallString($function, $paramIndex, " " x 2, $implClassName); + push(@implContentDecls, $functionCall); + push(@implContentDecls, " }\n"); + } + + if (BasicTypeCanFailConversion($parameter)) { + push(@implContentDecls, " bool ${parameterName}Ok;\n"); + } + + push(@implContentDecls, " " . GetNativeTypeFromSignature($parameter, 1) . " $parameterName = "); + push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]", + BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n"); + + if (TypeCanFailConversion($parameter)) { + $implIncludes{"ExceptionCode.h"} = 1; + push(@implContentDecls, +" if (!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ") {\n" . +" V8Proxy::setDOMException(TYPE_MISMATCH_ERR);\n" . +" return v8::Handle<v8::Value>();\n" . +" }\n"); + } + + if ($parameter->extendedAttributes->{"IsIndex"}) { + $implIncludes{"ExceptionCode.h"} = 1; + push(@implContentDecls, +" if ($parameterName < 0) {\n" . +" V8Proxy::setDOMException(INDEX_SIZE_ERR);\n" . +" return v8::Handle<v8::Value>();\n" . +" }\n"); + } + + $paramIndex++; + } + + # Build the function call string. + my $callString = GenerateFunctionCallString($function, $paramIndex, " ", $implClassName); + push(@implContentDecls, "$callString"); + push(@implContentDecls, " }\n\n"); +} + +sub GenerateBatchedAttributeData +{ + my $interfaceName = shift; + my $attributes = shift; + + foreach my $attribute (@$attributes) { + my $attrName = $attribute->signature->name; + my $attrExt = $attribute->signature->extendedAttributes; + + my $accessControl = "v8::DEFAULT"; + if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) { + $accessControl = "v8::ALL_CAN_READ"; + } elsif ($attrExt->{"DoNotCheckDomainSecurityOnSet"}) { + $accessControl = "v8::ALL_CAN_WRITE"; + } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) { + $accessControl = "v8::ALL_CAN_READ"; + if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) { + $accessControl .= "|v8::ALL_CAN_WRITE"; + } + } + if ($attrExt->{"V8DisallowShadowing"}) { + $accessControl .= "|v8::PROHIBITS_OVERWRITING"; + } + $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")"; + + my $customAccessor = + $attrExt->{"Custom"} || + $attrExt->{"CustomSetter"} || + $attrExt->{"CustomGetter"} || + $attrExt->{"V8Custom"} || + $attrExt->{"V8CustomSetter"} || + $attrExt->{"V8CustomGetter"} || + ""; + if ($customAccessor eq 1) { + # use the naming convension, interface + (capitalize) attr name + $customAccessor = $interfaceName . WK_ucfirst($attrName); + } + + my $getter; + my $setter; + my $propAttr = "v8::None"; + my $hasCustomSetter = 0; + + # Check attributes. + if ($attrExt->{"DontEnum"}) { + $propAttr .= "|v8::DontEnum"; + } + if ($attrExt->{"V8DisallowShadowing"}) { + $propAttr .= "|v8::DontDelete"; + } + + my $on_proto = "0 /* on instance */"; + my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */"; + + # Constructor + if ($attribute->signature->type =~ /Constructor$/) { + my $constructorType = $codeGenerator->StripModule($attribute->signature->type); + $constructorType =~ s/Constructor$//; + my $constructorIndex = uc($constructorType); + $data = "V8ClassIndex::${constructorIndex}"; + $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter"; + $setter = "0"; + $propAttr = "v8::ReadOnly"; + + # EventListeners + } elsif ($attribute->signature->type eq "EventListener") { + if ($interfaceName eq "DOMWindow") { + $getter = "V8Custom::v8DOMWindowEventHandlerAccessorGetter"; + $setter = "V8Custom::v8DOMWindowEventHandlerAccessorSetter"; + } elsif ($interfaceName eq "Element" || $interfaceName eq "Document" || $interfaceName eq "HTMLBodyElement" || $interfaceName eq "SVGElementInstance" || $interfaceName eq "HTMLFrameSetElement") { + $getter = "V8Custom::v8NodeEventHandlerAccessorGetter"; + $setter = "V8Custom::v8NodeEventHandlerAccessorSetter"; + } elsif ($interfaceName eq "DOMApplicationCache") { + $getter = "V8Custom::v8DOMApplicationCacheEventHandlerAccessorGetter"; + $setter = "V8Custom::v8DOMApplicationCacheEventHandlerAccessorSetter"; + } else { + $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + if ($interfaceName eq "WorkerContext" and $attrName eq "self") { + $setter = "0"; + $propAttr = "v8::ReadOnly"; + } else { + $setter = "V8Custom::v8${customAccessor}AccessorSetter"; + } + } + + # Custom Getter and Setter + } elsif ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { + $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + if ($interfaceName eq "WorkerContext" and $attrName eq "self") { + $setter = "0"; + $propAttr = "v8::ReadOnly"; + } else { + $hasCustomSetter = 1; + $setter = "V8Custom::v8${customAccessor}AccessorSetter"; + } + + # Custom Setter + } elsif ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"}) { + $hasCustomSetter = 1; + $getter = "${interfaceName}Internal::${attrName}AttrGetter"; + $setter = "V8Custom::v8${customAccessor}AccessorSetter"; + + # Custom Getter + } elsif ($attrExt->{"CustomGetter"}) { + $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + $setter = "${interfaceName}Internal::${attrName}AttrSetter"; + + # Replaceable + } elsif ($attrExt->{"Replaceable"}) { + # Replaceable accessor is put on instance template with ReadOnly attribute. + $getter = "${interfaceName}Internal::${attrName}AttrGetter"; + $setter = "0"; + + # Mark to avoid duplicate v8::ReadOnly flags in output. + $hasCustomSetter = 1; + + # Handle the special case of window.top being marked upstream as Replaceable. + # FIXME: Investigate why [Replaceable] is not marked as ReadOnly + # upstream and reach parity. + if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) { + $propAttr .= "|v8::ReadOnly"; + } + + # Normal + } else { + $getter = "${interfaceName}Internal::${attrName}AttrGetter"; + $setter = "${interfaceName}Internal::${attrName}AttrSetter"; + } + + if ($attrExt->{"Replaceable"} && !$hasCustomSetter) { + $setter = "0"; + $propAttr .= "|v8::ReadOnly"; + } + + # Read only attributes + if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) { + $setter = "0"; + } + + # An accessor can be installed on the proto + if ($attrExt->{"v8OnProto"}) { + $on_proto = "1 /* on proto */"; + } + + my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type . + "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; + + my $conditionalString = GenerateConditionalString($attribute->signature); + push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; + + push(@implContent, <<END); + // $commentInfo + { "$attrName", + $getter, + $setter, + $data, + $accessControl, + static_cast<v8::PropertyAttribute>($propAttr), + $on_proto }, +END + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; + } +} + + +sub GenerateImplementation +{ + my $object = shift; + my $dataNode = shift; + my $interfaceName = $dataNode->name; + my $className = "V8$interfaceName"; + my $implClassName = $interfaceName; + my $classIndex = uc($codeGenerator->StripModule($interfaceName)); + + my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; + my $conditionalString = GenerateConditionalString($dataNode); + + @allParents = $codeGenerator->FindParentsRecursively($dataNode); + + # - Add default header template + @implContentHeader = split("\r", $headerTemplate); + + push(@implFixedHeader, + "#include \"config.h\"\n" . + "#include \"V8Proxy.h\"\n" . + "#include \"V8Binding.h\"\n\n" . + "#undef LOG\n\n"); + + push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; + + if ($className =~ /^V8SVGAnimated/) { + AddIncludesForSVGAnimatedType($interfaceName); + } + + $implIncludes{"${className}.h"} = 1; + + AddIncludesForType($interfaceName); + $implIncludes{"V8Proxy.h"} = 1; + + push(@implContentDecls, "namespace WebCore {\n"); + push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n"); + push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n"); + + my $hasConstructors = 0; + + # Generate property accessors for attributes. + for ($index = 0; $index < @{$dataNode->attributes}; $index++) { + $attribute = @{$dataNode->attributes}[$index]; + $attrName = $attribute->signature->name; + $attrType = $attribute->signature->type; + + # Generate special code for the constructor attributes. + if ($attrType =~ /Constructor$/) { + $hasConstructors = 1; + next; + } + + # Make EventListeners always custom. + # FIXME: make the perl code capable of generating the + # event setters/getters. For now, WebKit has started removing the + # [Custom] attribute, so just automatically insert it to avoid forking + # other files. This should be okay because we can't generate stubs + # for any event getter/setters anyway. + if ($attrType eq "EventListener") { + $attribute->signature->extendedAttributes->{"Custom"} = 1; + $implIncludes{"V8CustomBinding.h"} = 1; + next; + } + + # Do not generate accessor if this is a custom attribute. The + # call will be forwarded to a hand-written accessor + # implementation. + if ($attribute->signature->extendedAttributes->{"Custom"} || + $attribute->signature->extendedAttributes->{"V8Custom"}) { + $implIncludes{"V8CustomBinding.h"} = 1; + next; + } + + # Generate the accessor. + if ($attribute->signature->extendedAttributes->{"CustomGetter"}) { + $implIncludes{"V8CustomBinding.h"} = 1; + } else { + GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName); + } + if ($attribute->signature->extendedAttributes->{"CustomSetter"} || + $attribute->signature->extendedAttributes->{"V8CustomSetter"}) { + $implIncludes{"V8CustomBinding.h"} = 1; + } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) { + $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!"; + # GenerateReplaceableAttrSetter($implClassName); + } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) { + GenerateNormalAttrSetter($attribute, $dataNode, $classIndex, $implClassName); + } + } + + if ($hasConstructors) { + GenerateConstructorGetter($implClassName, $classIndex); + } + + # Generate methods for functions. + foreach my $function (@{$dataNode->functions}) { + # hack for addEventListener/RemoveEventListener + # FIXME: avoid naming conflict + if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"}) { + $implIncludes{"V8CustomBinding.h"} = 1; + } else { + GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName); + } + + # If the function does not need domain security check, we need to + # generate an access getter that returns different function objects + # for different calling context. + if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { + GenerateDomainSafeFunctionGetter($function, $dataNode, $classIndex, $implClassName); + } + } + + # Attributes + my $attributes = $dataNode->attributes; + + # For the DOMWindow interface we partition the attributes into the + # ones that disallows shadowing and the rest. + my @disallows_shadowing; + my @normal; + if ($interfaceName eq "DOMWindow") { + foreach my $attribute (@$attributes) { + if ($attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) { + push(@disallows_shadowing, $attribute); + } else { + push(@normal, $attribute); + } + } + # Put the attributes that disallow shadowing on the shadow object. + $attributes = \@normal; + push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n"); + GenerateBatchedAttributeData($interfaceName, \@disallows_shadowing); + push(@implContent, "};\n"); + } + + my $has_attributes = 0; + if (@$attributes) { + $has_attributes = 1; + push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n"); + GenerateBatchedAttributeData($interfaceName, $attributes); + push(@implContent, "};\n"); + } + + # Setup constants + my $has_constants = 0; + if (@{$dataNode->constants}) { + $has_constants = 1; + push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n"); + } + foreach my $constant (@{$dataNode->constants}) { + my $name = $constant->name; + my $value = $constant->value; + # FIXME: we need the static_cast here only because of one constant, NodeFilter.idl + # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we + # handled this here, and converted it to a -1 constant in the c++ output. + push(@implContent, <<END); + { "${name}", static_cast<signed int>($value) }, +END + } + if ($has_constants) { + push(@implContent, "};\n"); + } + + push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n"); + + my $access_check = "/* no access check */"; + if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) { + $access_check = "instance->SetAccessCheckCallbacks(V8Custom::v8${interfaceName}NamedSecurityCheck, V8Custom::v8${interfaceName}IndexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));"; + } + + # For the DOMWindow interface, generate the shadow object template + # configuration method. + if ($implClassName eq "DOMWindow") { + push(@implContent, <<END); +static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) { + batchConfigureAttributes(templ, + v8::Handle<v8::ObjectTemplate>(), + shadow_attrs, + sizeof(shadow_attrs)/sizeof(*shadow_attrs)); + return templ; +} +END + } + + # Generate the template configuration method + push(@implContent, <<END); +static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) { + v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); +END + if (IsNodeSubType($dataNode)) { + push(@implContent, <<END); + instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount); +END + } else { + push(@implContent, <<END); + instance->SetInternalFieldCount(V8Custom::kDefaultWrapperInternalFieldCount); +END + } + + push(@implContent, <<END); + v8::Local<v8::Signature> default_signature = v8::Signature::New(desc); + v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); + $access_check +END + + + # Set up our attributes if we have them + if ($has_attributes) { + push(@implContent, <<END); + batchConfigureAttributes(instance, proto, ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs)); +END + } + + # Define our functions with Set() or SetAccessor() + foreach my $function (@{$dataNode->functions}) { + my $attrExt = $function->signature->extendedAttributes; + my $name = $function->signature->name; + + my $property_attributes = "v8::DontDelete"; + if ($attrExt->{"DontEnum"}) { + $property_attributes .= "|v8::DontEnum"; + } + if ($attrExt->{"V8ReadOnly"}) { + $property_attributes .= "|v8::ReadOnly"; + } + + my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; + + my $template = "proto"; + if ($attrExt->{"V8OnInstance"}) { + $template = "instance"; + } + + if ($attrExt->{"DoNotCheckDomainSecurity"} && + ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) { + # Mark the accessor as ReadOnly and set it on the proto object so + # it can be shadowed. This is really a hack to make it work. + # There are several sceneria to call into the accessor: + # 1) from the same domain: "window.open": + # the accessor finds the DOM wrapper in the proto chain; + # 2) from the same domain: "window.__proto__.open": + # the accessor will NOT find a DOM wrapper in the prototype chain + # 3) from another domain: "window.open": + # the access find the DOM wrapper in the prototype chain + # "window.__proto__.open" from another domain will fail when + # accessing '__proto__' + # + # The solution is very hacky and fragile, it really needs to be replaced + # by a better solution. + $property_attributes .= "|v8::ReadOnly"; + push(@implContent, <<END); + + // $commentInfo + $template->SetAccessor( + v8::String::New("$name"), + ${interfaceName}Internal::${name}AttrGetter, + 0, + v8::Handle<v8::Value>(), + v8::ALL_CAN_READ, + static_cast<v8::PropertyAttribute>($property_attributes)); +END + next; + } + + my $signature = "default_signature"; + if ($attrExt->{"V8DoNotCheckSignature"}){ + $signature = "v8::Local<v8::Signature>()"; + } + + if (RequiresCustomSignature($function)) { + $signature = "${name}_signature"; + push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function)); + } + + # Normal function call is a template + my $templateFunction = GenerateNewFunctionTemplate($function, $dataNode, $signature); + + + push(@implContent, <<END); + + // $commentInfo + ${template}->Set( + v8::String::New("$name"), + $templateFunction, + static_cast<v8::PropertyAttribute>($property_attributes)); +END + } + + # set the super descriptor + foreach (@{$dataNode->parents}) { + my $parent = $codeGenerator->StripModule($_); + if ($parent eq "EventTarget") { next; } + $implIncludes{"V8${parent}.h"} = 1; + my $parentClassIndex = uc($codeGenerator->StripModule($parent)); + push(@implContent, " desc->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::${parentClassIndex}));\n"); + last; + } + + # Set the class name. This is used when printing objects. + push(@implContent, " desc->SetClassName(v8::String::New(\"" . GetClassName(${interfaceName}) . "\"));\n"); + + if ($has_constants) { + push(@implContent, <<END); + batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts)); +END + } + + push(@implContent, <<END); + return desc; +} + +v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() { + static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_; + if (${className}_raw_cache_.IsEmpty()) { + v8::HandleScope scope; + v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8Proxy::checkNewLegal); + ${className}_raw_cache_ = v8::Persistent<v8::FunctionTemplate>::New(result); + } + return ${className}_raw_cache_; +} + +v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() { + static v8::Persistent<v8::FunctionTemplate> ${className}_cache_; + if (${className}_cache_.IsEmpty()) + ${className}_cache_ = Configure${className}Template(GetRawTemplate()); + return ${className}_cache_; +} + +bool ${className}::HasInstance(v8::Handle<v8::Value> value) { + return GetRawTemplate()->HasInstance(value); +} + +END + + if ($implClassName eq "DOMWindow") { + push(@implContent, <<END); +v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() { + static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_; + if (V8DOMWindowShadowObject_cache_.IsEmpty()) { + V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New()); + ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_); + } + return V8DOMWindowShadowObject_cache_; +} +END + } + + push(@implContent, <<END); +} // namespace WebCore +END + + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; +} + + +sub GenerateFunctionCallString() +{ + my $function = shift; + my $numberOfParameters = shift; + my $indent = shift; + my $implClassName = shift; + + my $name = $function->signature->name; + my $isPodType = IsPodType($implClassName); + my $returnType = GetTypeFromSignature($function->signature); + my $returnsPodType = IsPodType($returnType); + my $nativeReturnType = GetNativeType($returnType, 0); + my $result = ""; + + # Special case: SVG matrix transform methods should not mutate + # the matrix but return a copy + my $copyFirst = 0; + if ($implClassName eq "SVGMatrix" && $function->signature->type eq "SVGMatrix") { + $copyFirst = 1; + } + + if ($function->signature->extendedAttributes->{"v8implname"}) { + $name = $function->signature->extendedAttributes->{"v8implname"}; + } + + if ($function->signature->extendedAttributes->{"ImplementationFunction"}) { + $name = $function->signature->extendedAttributes->{"ImplementationFunction"}; + } + + my $functionString = "imp->${name}("; + + if ($copyFirst) { + $functionString = "result.${name}("; + } + + my $returnsListItemPodType = 0; + # SVG lists functions that return POD types require special handling + if (IsSVGListTypeNeedingSpecialHandling($implClassName) && IsSVGListMethod($name) && $returnsPodType) { + $returnsListItemPodType = 1; + $result .= $indent . "SVGList<RefPtr<SVGPODListItem<$nativeReturnType> > >* listImp = imp;\n"; + $functionString = "listImp->${name}("; + } + + my $first = 1; + my $index = 0; + my $nodeToReturn = 0; + + foreach my $parameter (@{$function->parameters}) { + if ($index eq $numberOfParameters) { + last; + } + if ($first) { $first = 0; } + else { $functionString .= ", "; } + my $paramName = $parameter->name; + my $paramType = $parameter->type; + + # This is a bit of a hack... we need to convert parameters to methods on SVG lists + # of POD types which are items in the list to appropriate SVGList<> instances + if ($returnsListItemPodType && $paramType . "List" eq $implClassName) { + $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)"; + } + + if ($parameter->type eq "NodeFilter") { + $functionString .= "$paramName.get()"; + } else { + $functionString .= $paramName; + } + + if ($parameter->extendedAttributes->{"Return"}) { + $nodeToReturn = $parameter->name; + } + $index++; + } + + if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { + $functionString .= ", " if not $first; + $functionString .= "&callStack"; + if ($first) { $first = 0; } + } + + if (@{$function->raisesExceptions}) { + $functionString .= ", " if not $first; + $functionString .= "ec"; + } + $functionString .= ")"; + + if ($nodeToReturn) { + # Special case for insertBefore, replaceChild, removeChild and + # appendChild functions from Node. + $result .= $indent . "bool success = $functionString;\n"; + if (@{$function->raisesExceptions}) { + $result .= GenerateSetDOMException($indent); + } + $result .= $indent . "if (success)\n"; + $result .= $indent . " " . + "return V8DOMWrapper::convertNodeToV8Object($nodeToReturn);\n"; + $result .= $indent . "return v8::Null();\n"; + return $result; + } elsif ($returnType eq "void") { + $result .= $indent . "$functionString;\n"; + } elsif ($copyFirst) { + $result .= + $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . + $indent . "$functionString;\n"; + } elsif ($returnsListItemPodType) { + $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n"; + } else { + $result .= $indent . $nativeReturnType . " result = $functionString;\n"; + } + + if (@{$function->raisesExceptions}) { + $result .= GenerateSetDOMException($indent); + } + + my $return = "result"; + + # If the return type is a POD type, separate out the wrapper generation + if ($returnsListItemPodType) { + $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = "; + $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">::create($return, imp->associatedAttributeName());\n"; + $return = "wrapper"; + } elsif ($returnsPodType) { + $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = "; + $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n"; + $return = "wrapper"; + } + + my $generatedSVGContextRetrieval = 0; + # If the return type needs an SVG context, output it + if (IsSVGTypeNeedingContextParameter($returnType)) { + $result .= GenerateSVGContextAssignment($implClassName, $return . ".get()", $indent); + $generatedSVGContextRetrieval = 1; + } + + if (IsSVGTypeNeedingContextParameter($implClassName) && $implClassName =~ /List$/ && IsSVGListMutator($name)) { + if (!$generatedSVGContextRetrieval) { + $result .= GenerateSVGContextRetrieval($implClassName, $indent); + $generatedSVGContextRetrieval = 1; + } + + $result .= $indent . "context->svgAttributeChanged(imp->associatedAttributeName());\n"; + $implIncludes{"SVGElement.h"} = 1; + } + + # If the implementing class is a POD type, commit changes + if ($isPodType) { + if (!$generatedSVGContextRetrieval) { + $result .= GenerateSVGContextRetrieval($implClassName, $indent); + $generatedSVGContextRetrieval = 1; + } + + $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n"; + } + + if ($returnsPodType) { + my $classIndex = uc($returnType); + $result .= $indent . "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n"; + } else { + $return .= ".release()" if (IsRefPtrType($returnType)); + $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n"; + } + + return $result; +} + + +# Get the class name used for printing javascript DOM-object wrappers. +sub GetClassName +{ + my $type = shift; + return "HTMLCollection" if $type eq "HTMLAllCollection"; + return $type; +} + + +sub GetTypeFromSignature +{ + my $signature = shift; + + my $type = $codeGenerator->StripModule($signature->type); + if (($type eq "DOMString") && $signature->extendedAttributes->{"V8Custom"}) { + $type = "AtomicString"; + } + + return $type; +} + + +sub GetNativeTypeFromSignature +{ + my $signature = shift; + my $isParameter = shift; + + my $type = GetTypeFromSignature($signature); + + return GetNativeType($type, $isParameter); +} + +sub IsRefPtrType +{ + my $type = shift; + return 1 if $type eq "Attr"; + return 1 if $type eq "CanvasGradient"; + return 1 if $type eq "ClientRect"; + return 1 if $type eq "ClientRectList"; + return 1 if $type eq "CDATASection"; + return 1 if $type eq "Comment"; + return 1 if $type eq "CSSRule"; + return 1 if $type eq "CSSStyleRule"; + return 1 if $type eq "CSSCharsetRule"; + return 1 if $type eq "CSSImportRule"; + return 1 if $type eq "CSSMediaRule"; + return 1 if $type eq "CSSFontFaceRule"; + return 1 if $type eq "CSSPageRule"; + return 1 if $type eq "CSSPrimitiveValue"; + return 1 if $type eq "CSSStyleSheet"; + return 1 if $type eq "CSSStyleDeclaration"; + return 1 if $type eq "CSSValue"; + return 1 if $type eq "CSSRuleList"; + return 1 if $type eq "Database"; + return 1 if $type eq "Document"; + return 1 if $type eq "DocumentFragment"; + return 1 if $type eq "DocumentType"; + return 1 if $type eq "Element"; + return 1 if $type eq "EntityReference"; + return 1 if $type eq "Event"; + return 1 if $type eq "FileList"; + return 1 if $type eq "HTMLCollection"; + return 1 if $type eq "HTMLDocument"; + return 1 if $type eq "HTMLElement"; + return 1 if $type eq "HTMLOptionsCollection"; + return 1 if $type eq "ImageData"; + return 1 if $type eq "Media"; + return 1 if $type eq "MediaError"; + return 1 if $type eq "MimeType"; + return 1 if $type eq "Node"; + return 1 if $type eq "NodeList"; + return 1 if $type eq "NodeFilter"; + return 1 if $type eq "NodeIterator"; + return 1 if $type eq "NSResolver"; + return 1 if $type eq "Plugin"; + return 1 if $type eq "ProcessingInstruction"; + return 1 if $type eq "Range"; + return 1 if $type eq "Text"; + return 1 if $type eq "TextMetrics"; + return 1 if $type eq "TimeRanges"; + return 1 if $type eq "TreeWalker"; + return 1 if $type eq "WebKitCSSMatrix"; + return 1 if $type eq "WebKitPoint"; + return 1 if $type eq "XPathExpression"; + return 1 if $type eq "XPathNSResolver"; + return 1 if $type eq "XPathResult"; + + return 1 if $type eq "SVGAngle"; + return 1 if $type eq "SVGElementInstance"; + return 1 if $type eq "SVGElementInstanceList"; + return 1 if $type =~ /^SVGPathSeg/; + + return 1 if $type =~ /^SVGAnimated/; + + return 0; +} + +sub IsVideoClassName +{ + my $class = shift; + return 1 if $class eq "V8HTMLAudioElement"; + return 1 if $class eq "V8HTMLMediaElement"; + return 1 if $class eq "V8HTMLSourceElement"; + return 1 if $class eq "V8HTMLVideoElement"; + return 1 if $class eq "V8MediaError"; + return 1 if $class eq "V8TimeRanges"; + + return 0; +} + +sub IsWorkerClassName +{ + my $class = shift; + return 1 if $class eq "V8Worker"; + return 1 if $class eq "V8WorkerContext"; + return 1 if $class eq "V8WorkerLocation"; + return 1 if $class eq "V8WorkerNavigator"; + + return 0; +} + +sub GetNativeType +{ + my $type = shift; + my $isParameter = shift; + + if ($type eq "float" or $type eq "AtomicString" or $type eq "double") { + return $type; + } + + return "int" if $type eq "int"; + return "int" if $type eq "short" or $type eq "unsigned short"; + return "int" if $type eq "long" or $type eq "unsigned long"; + return "unsigned long long" if $type eq "unsigned long long"; + return "bool" if $type eq "boolean"; + return "String" if $type eq "DOMString"; + return "Range::CompareHow" if $type eq "CompareHow"; + return "FloatRect" if $type eq "SVGRect"; + return "FloatPoint" if $type eq "SVGPoint"; + return "TransformationMatrix" if $type eq "SVGMatrix"; + return "SVGTransform" if $type eq "SVGTransform"; + return "SVGLength" if $type eq "SVGLength"; + return "double" if $type eq "SVGNumber"; + return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType"; + return "DOMTimeStamp" if $type eq "DOMTimeStamp"; + return "unsigned" if $type eq "unsigned int"; + return "Node*" if $type eq "EventTarget" and $isParameter; + + return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack? + + # temporary hack + return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; + + return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter; + + # Default, assume native type is a pointer with same type name as idl type + return "${type}*"; +} + + +my %typeCanFailConversion = ( + "AtomicString" => 0, + "Attr" => 1, + "CompareHow" => 0, + "DataGridColumn" => 0, + "DOMString" => 0, + "DOMWindow" => 0, + "DocumentType" => 0, + "Element" => 0, + "Event" => 0, + "EventListener" => 0, + "EventTarget" => 0, + "HTMLElement" => 0, + "HTMLOptionElement" => 0, + "Node" => 0, + "NodeFilter" => 0, + "MessagePort" => 0, + "NSResolver" => 0, + "Range" => 0, + "SQLResultSet" => 0, + "Storage" => 0, + "SVGAngle" => 0, + "SVGElement" => 0, + "SVGLength" => 1, + "SVGMatrix" => 1, + "SVGNumber" => 0, + "SVGPaintType" => 0, + "SVGPathSeg" => 0, + "SVGPoint" => 1, + "SVGRect" => 1, + "SVGTransform" => 1, + "VoidCallback" => 1, + "WebKitCSSMatrix" => 0, + "WebKitPoint" => 0, + "XPathEvaluator" => 0, + "XPathNSResolver" => 0, + "XPathResult" => 0, + "boolean" => 0, + "double" => 0, + "float" => 0, + "long" => 0, + "unsigned long" => 0, + "unsigned short" => 0, +); + + +sub TranslateParameter +{ + my $signature = shift; + + # The IDL uses some pseudo-types which don't really exist. + if ($signature->type eq "TimeoutHandler") { + $signature->type("DOMString"); + } +} + +sub BasicTypeCanFailConversion +{ + my $signature = shift; + my $type = GetTypeFromSignature($signature); + + return 1 if $type eq "SVGLength"; + return 1 if $type eq "SVGMatrix"; + return 1 if $type eq "SVGPoint"; + return 1 if $type eq "SVGRect"; + return 1 if $type eq "SVGTransform"; + return 0; +} + +sub TypeCanFailConversion +{ + my $signature = shift; + + my $type = GetTypeFromSignature($signature); + + $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr"; + + return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type}; + + die "Don't know whether a JS value can fail conversion to type $type."; +} + +sub JSValueToNative +{ + my $signature = shift; + my $value = shift; + my $okParam = shift; + my $maybeOkParam = $okParam ? ", ${okParam}" : ""; + + my $type = GetTypeFromSignature($signature); + + return "$value" if $type eq "JSObject"; + return "$value->BooleanValue()" if $type eq "boolean"; + return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double"; + return "$value->NumberValue()" if $type eq "SVGNumber"; + + return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long"; + return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow"; + return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType"; + + return "v8ValueToAtomicWebCoreString($value)" if $type eq "AtomicString"; + return "toWebCoreString($value)" if $type eq "DOMUserData"; + if ($type eq "DOMString") { + return "toWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"}; + return "toWebCoreStringWithNullOrUndefinedCheck($value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}; + return "toWebCoreString($value)"; + } + + if ($type eq "NodeFilter") { + return "V8DOMWrapper::wrapNativeNodeFilter($value)"; + } + + if ($type eq "SVGRect") { + $implIncludes{"FloatRect.h"} = 1; + } + + if ($type eq "SVGPoint") { + $implIncludes{"FloatPoint.h"} = 1; + } + + # Default, assume autogenerated type conversion routines + $implIncludes{"V8Proxy.h"} = 1; + if ($type eq "EventTarget") { + $implIncludes{"V8Node.h"} = 1; + + # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget. + return "V8Node::HasInstance($value) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0"; + } + + AddIncludesForType($type); + # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type); + + if (IsDOMNodeType($type)) { + $implIncludes{"V8${type}.h"} = 1; + + # Perform type checks on the parameter, if it is expected Node type, + # return NULL. + return "V8${type}::HasInstance($value) ? V8DOMWrapper::convertDOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0"; + } else { + # TODO: Temporary to avoid Window name conflict. + my $classIndex = uc($type); + my $implClassName = ${type}; + + $implIncludes{"V8$type.h"} = 1; + + if (IsPodType($type)) { + my $nativeType = GetNativeType($type); + $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; + + return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})" + } + + $implIncludes{"V8${type}.h"} = 1; + + # Perform type checks on the parameter, if it is expected Node type, + # return NULL. + return "V8${type}::HasInstance($value) ? V8DOMWrapper::convertToNativeObject<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0"; + } +} + + +sub GetV8HeaderName +{ + my $type = shift; + return "V8" . GetImplementationFileName($type); +} + + +sub CreateCustomSignature +{ + my $function = shift; + my $count = @{$function->parameters}; + my $name = $function->signature->name; + my $result = " const int ${name}_argc = ${count};\n" . + " v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { "; + my $first = 1; + foreach my $parameter (@{$function->parameters}) { + if ($first) { $first = 0; } + else { $result .= ", "; } + if (IsWrapperType($parameter->type)) { + my $type = $parameter->type; + my $header = GetV8HeaderName($type); + $implIncludes{$header} = 1; + $result .= "V8${type}::GetRawTemplate()"; + } else { + $result .= "v8::Handle<v8::FunctionTemplate>()"; + } + } + $result .= " };\n"; + $result .= " v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n"; + return $result; +} + + +sub RequiresCustomSignature +{ + my $function = shift; + # No signature needed for Custom function + if ($function->signature->extendedAttributes->{"Custom"} || + $function->signature->extendedAttributes->{"V8Custom"}) { + return 0; + } + + foreach my $parameter (@{$function->parameters}) { + if (IsWrapperType($parameter->type)) { + return 1; + } + } + return 0; +} + + +my %non_wrapper_types = ( + 'float' => 1, + 'AtomicString' => 1, + 'double' => 1, + 'short' => 1, + 'unsigned short' => 1, + 'long' => 1, + 'unsigned long' => 1, + 'boolean' => 1, + 'DOMString' => 1, + 'CompareHow' => 1, + 'SVGRect' => 1, + 'SVGPoint' => 1, + 'SVGMatrix' => 1, + 'SVGTransform' => 1, + 'SVGLength' => 1, + 'SVGNumber' => 1, + 'SVGPaintType' => 1, + 'DOMTimeStamp' => 1, + 'JSObject' => 1, + 'EventTarget' => 1, + 'NodeFilter' => 1, + 'EventListener' => 1 +); + + +sub IsWrapperType +{ + my $type = $codeGenerator->StripModule(shift); + return !($non_wrapper_types{$type}); +} + +sub IsDOMNodeType +{ + my $type = shift; + + return 1 if $type eq 'Attr'; + return 1 if $type eq 'CDATASection'; + return 1 if $type eq 'Comment'; + return 1 if $type eq 'Document'; + return 1 if $type eq 'DocumentFragment'; + return 1 if $type eq 'DocumentType'; + return 1 if $type eq 'Element'; + return 1 if $type eq 'EntityReference'; + return 1 if $type eq 'HTMLCanvasElement'; + return 1 if $type eq 'HTMLDocument'; + return 1 if $type eq 'HTMLElement'; + return 1 if $type eq 'HTMLFormElement'; + return 1 if $type eq 'HTMLTableCaptionElement'; + return 1 if $type eq 'HTMLTableSectionElement'; + return 1 if $type eq 'Node'; + return 1 if $type eq 'ProcessingInstruction'; + return 1 if $type eq 'SVGElement'; + return 1 if $type eq 'SVGDocument'; + return 1 if $type eq 'SVGSVGElement'; + return 1 if $type eq 'SVGUseElement'; + return 1 if $type eq 'Text'; + + return 0; +} + + +sub ReturnNativeToJSValue +{ + my $signature = shift; + my $value = shift; + my $indent = shift; + my $type = GetTypeFromSignature($signature); + my $className= "V8$type"; + + return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp"; + return "return $value ? v8::True() : v8::False()" if $type eq "boolean"; + return "return v8::Undefined()" if $type eq "void"; + + # For all the types where we use 'int' as the representation type, + # we use Integer::New which has a fast Smi conversion check. + return "return v8::Integer::New($value)" if GetNativeType($type) eq "int"; + + return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; + + if ($codeGenerator->IsStringType($type)) { + my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"}; + if (defined $conv) { + return "return v8StringOrNull($value)" if $conv eq "Null"; + return "return v8StringOrUndefined($value)" if $conv eq "Undefined"; + return "return v8StringOrFalse($value)" if $conv eq "False"; + + die "Unknown value for ConvertNullStringTo extended attribute"; + } + return "return v8String($value)"; + } + + # V8 specific. + my $implClassName = $type; + AddIncludesForType($type); + # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type); + + # special case for non-DOM node interfaces + if (IsDOMNodeType($type)) { + return "return V8DOMWrapper::convertNodeToV8Object($value)"; + } + + if ($type eq "EventTarget" or $type eq "SVGElementInstance") { + return "return V8DOMWrapper::convertEventTargetToV8Object($value)"; + } + + if ($type eq "Event") { + return "return V8DOMWrapper::convertEventToV8Object($value)"; + } + + if ($type eq "EventListener") { + return "return V8DOMWrapper::convertEventListenerToV8Object($value)"; + } + + if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") { + $implIncludes{"WorkerContextExecutionProxy.h"} = 1; + return "return WorkerContextExecutionProxy::convertWorkerContextToV8Object($value)"; + } + + if ($type eq "WorkerLocation" or $type eq "WorkerNavigator") { + $implIncludes{"WorkerContextExecutionProxy.h"} = 1; + my $classIndex = uc($type); + + return "return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::$classIndex, $value)"; + } + + else { + $implIncludes{"wtf/RefCounted.h"} = 1; + $implIncludes{"wtf/RefPtr.h"} = 1; + $implIncludes{"wtf/GetPtr.h"} = 1; + my $classIndex = uc($type); + + if (IsPodType($type)) { + $value = GenerateSVGStaticPodTypeWrapper($type, $value); + } + + return "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, $value)"; + } +} + +sub GenerateSVGStaticPodTypeWrapper { + my $type = shift; + my $value = shift; + + $implIncludes{"V8$type.h"}=1; + $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; + + my $nativeType = GetNativeType($type); + return "V8SVGStaticPODTypeWrapper<$nativeType>::create($value)"; +} + +# Internal helper +sub WriteData +{ + if (defined($IMPL)) { + # Write content to file. + print $IMPL @implContentHeader; + + print $IMPL @implFixedHeader; + + foreach my $implInclude (sort keys(%implIncludes)) { + my $checkType = $implInclude; + $checkType =~ s/\.h//; + + print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType); + } + + print $IMPL "\n"; + print $IMPL @implContentDecls; + print $IMPL @implContent; + close($IMPL); + undef($IMPL); + + %implIncludes = (); + @implFixedHeader = (); + @implHeaderContent = (); + @implContentDecls = (); + @implContent = (); + } + + if (defined($HEADER)) { + # Write content to file. + print $HEADER @headerContent; + close($HEADER); + undef($HEADER); + + @headerContent = (); + } +} + +sub IsSVGTypeNeedingContextParameter +{ + my $implClassName = shift; + + if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) { + return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/; + } + + return 0; +} + +sub GenerateSVGContextAssignment +{ + my $srcType = shift; + my $value = shift; + my $indent = shift; + + $result = GenerateSVGContextRetrieval($srcType, $indent); + $result .= $indent . "V8Proxy::setSVGContext($value, context);\n"; + + return $result; +} + +sub GenerateSVGContextRetrieval +{ + my $srcType = shift; + my $indent = shift; + + my $srcIsPodType = IsPodType($srcType); + + my $srcObject = "imp"; + if ($srcIsPodType) { + $srcObject = "imp_wrapper"; + } + + my $contextDecl; + + if (IsSVGTypeNeedingContextParameter($srcType)) { + $contextDecl = "V8Proxy::svgContext($srcObject)"; + } else { + $contextDecl = $srcObject; + } + + return $indent . "SVGElement* context = $contextDecl;\n"; +} + +sub IsSVGListMutator +{ + my $functionName = shift; + + return 1 if $functionName eq "clear"; + return 1 if $functionName eq "initialize"; + return 1 if $functionName eq "insertItemBefore"; + return 1 if $functionName eq "replaceItem"; + return 1 if $functionName eq "removeItem"; + return 1 if $functionName eq "appendItem"; + + return 0; +} + +sub IsSVGListMethod +{ + my $functionName = shift; + + return 1 if $functionName eq "getFirst"; + return 1 if $functionName eq "getLast"; + return 1 if $functionName eq "getItem"; + + return IsSVGListMutator($functionName); +} + +sub IsSVGListTypeNeedingSpecialHandling +{ + my $className = shift; + + return 1 if $className eq "SVGPointList"; + return 1 if $className eq "SVGTransformList"; + + return 0; +} + +sub DebugPrint +{ + my $output = shift; + + print $output; + print "\n"; +} diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm index de7cf9c..c4cb041 100644 --- a/WebCore/bindings/scripts/IDLParser.pm +++ b/WebCore/bindings/scripts/IDLParser.pm @@ -41,6 +41,7 @@ my $preservedParseMode = MODE_UNDEF; my $beQuiet; # Should not display anything on STDOUT? my $document = 0; # Will hold the resulting 'idlDocument' +my $parentsOnly = 0; # If 1, parse only enough to populate parents list # Default Constructor sub new @@ -62,6 +63,7 @@ sub Parse my $fileName = shift; my $defines = shift; my $preprocessor = shift; + $parentsOnly = shift; if (!$preprocessor) { $preprocessor = "/usr/bin/gcc -E -P -x c++"; @@ -240,6 +242,8 @@ sub ParseInterface push(@$arrayRef, $line); } + return if $parentsOnly; + $interfaceData =~ s/[\n\r]/ /g; my @interfaceMethods = split(/;/, $interfaceData); diff --git a/WebCore/bindings/v8/ChildThreadDOMData.cpp b/WebCore/bindings/v8/ChildThreadDOMData.cpp new file mode 100644 index 0000000..77ce0f4 --- /dev/null +++ b/WebCore/bindings/v8/ChildThreadDOMData.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ChildThreadDOMData.h" + +namespace WebCore { + +ChildThreadDOMData::ChildThreadDOMData() + : m_defaultStore(this) +{ +} + +DOMDataStore& ChildThreadDOMData::getStore() +{ + ASSERT(!WTF::isMainThread()); + // Currently, child threads have only one world. + return m_defaultStore; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ChildThreadDOMData.h b/WebCore/bindings/v8/ChildThreadDOMData.h new file mode 100644 index 0000000..5097c86 --- /dev/null +++ b/WebCore/bindings/v8/ChildThreadDOMData.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ChildThreadDOMData_h +#define ChildThreadDOMData_h + +#include "DOMData.h" +#include "ScopedDOMDataStore.h" + +namespace WebCore { + + class ChildThreadDOMData : public DOMData { + public: + ChildThreadDOMData(); + DOMDataStore& getStore(); + + private: + ScopedDOMDataStore m_defaultStore; + }; + +} // namespace WebCore + +#endif // ChildThreadDOMData_h diff --git a/WebCore/bindings/v8/DOMData.cpp b/WebCore/bindings/v8/DOMData.cpp new file mode 100644 index 0000000..07254fe --- /dev/null +++ b/WebCore/bindings/v8/DOMData.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DOMData.h" + +#include "ChildThreadDOMData.h" +#include "MainThreadDOMData.h" + +namespace WebCore { + +DOMData::DOMData() + : m_delayedProcessingScheduled(false) + , m_isMainThread(WTF::isMainThread()) + , m_owningThread(WTF::currentThread()) +{ +} + +DOMData* DOMData::getCurrent() +{ + if (WTF::isMainThread()) + return getCurrentMainThread(); + + DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<ChildThreadDOMData>, childThreadDOMData, ()); + return childThreadDOMData; +} + +DOMData* DOMData::getCurrentMainThread() +{ + ASSERT(WTF::isMainThread()); + DEFINE_STATIC_LOCAL(MainThreadDOMData, mainThreadDOMData, ()); + return &mainThreadDOMData; +} + +void DOMData::ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject) +{ + if (m_owningThread == WTF::currentThread()) { + // No need to delay the work. We can deref right now. + derefObject(type, domObject); + return; + } + + // We need to do the deref on the correct thread. + m_delayedObjectMap.set(domObject, type); + + // Post a task to the owning thread in order to process the delayed queue. + // FIXME: For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker. + if (!m_delayedProcessingScheduled) { + m_delayedProcessingScheduled = true; + if (isMainThread()) + WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0); + } +} + +void DOMData::derefObject(V8ClassIndex::V8WrapperType type, void* domObject) +{ + switch (type) { + case V8ClassIndex::NODE: + static_cast<Node*>(domObject)->deref(); + break; + +#define MakeCase(type, name) \ + case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; + DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active. +#undef MakeCase + +#if ENABLE(SVG) +#define MakeCase(type, name) \ + case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; + SVG_OBJECT_TYPES(MakeCase) // This also includes SVGElementInstance. +#undef MakeCase + +#define MakeCase(type, name) \ + case V8ClassIndex::type: \ + static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break; + SVG_POD_NATIVE_TYPES(MakeCase) +#undef MakeCase +#endif + + default: + ASSERT_NOT_REACHED(); + break; + } +} + +void DOMData::derefDelayedObjects() +{ + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + + m_delayedProcessingScheduled = false; + + for (DelayedObjectMap::iterator iter(m_delayedObjectMap.begin()); iter != m_delayedObjectMap.end(); ++iter) + derefObject(iter->second, iter->first); + + m_delayedObjectMap.clear(); +} + +void DOMData::derefDelayedObjectsInCurrentThread(void*) +{ + getCurrent()->derefDelayedObjects(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h new file mode 100644 index 0000000..5effe7c --- /dev/null +++ b/WebCore/bindings/v8/DOMData.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DOMData_h +#define DOMData_h + +#include "DOMDataStore.h" + +namespace WebCore { + + // DOMData + // + // DOMData represents the all the DOM wrappers for a given thread. In + // particular, DOMData holds wrappers for all the isolated worlds in the + // thread. The DOMData for the main thread and the DOMData for child threads + // use different subclasses. + // + class DOMData : public Noncopyable { + public: + DOMData(); + + static DOMData* getCurrent(); + static DOMData* getCurrentMainThread(); // Caller must be on the main thread. + virtual DOMDataStore& getStore() = 0; + + template<typename T> + static void handleWeakObject(DOMDataStore::DOMWrapperMapType, v8::Handle<v8::Object>, T* domObject); + + void forgetDelayedObject(void* object) { m_delayedObjectMap.take(object); } + + // This is to ensure that we will deref DOM objects from the owning thread, + // not the GC thread. The helper function will be scheduled by the GC + // thread to get called from the owning thread. + static void derefDelayedObjectsInCurrentThread(void*); + void derefDelayedObjects(); + + template<typename T> + static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap); + + ThreadIdentifier owningThread() const { return m_owningThread; } + + private: + typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap; + + void ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject); + static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject); + + // Stores all the DOM objects that are delayed to be processed when the + // owning thread gains control. + DelayedObjectMap m_delayedObjectMap; + + // The flag to indicate if the task to do the delayed process has + // already been posted. + bool m_delayedProcessingScheduled; + + bool m_isMainThread; + ThreadIdentifier m_owningThread; + }; + + // Called when the dead object is not in GC thread's map. Go through all + // thread maps to find the one containing it. Then clear the JS reference + // and push the DOM object into the delayed queue for it to be deref-ed at + // later time from the owning thread. + // + // * This is called when the GC thread is not the owning thread. + // * This can be called on any thread that has GC running. + // * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency. + // + template<typename T> + void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Handle<v8::Object> v8Object, T* domObject) + { + + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + + DOMDataStore::InternalDOMWrapperMap<T>* domMap = static_cast<DOMDataStore::InternalDOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); + + v8::Handle<v8::Object> wrapper = domMap->get(domObject); + if (*wrapper == *v8Object) { + // Clear the JS reference. + domMap->forgetOnly(domObject); + store->domData()->ensureDeref(V8DOMWrapper::domWrapperType(v8Object), domObject); + } + } + } + + template<typename T> + void DOMData::removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) + { + for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) { + T* domObject = static_cast<T*>(iter->first); + v8::Persistent<v8::Object> v8Object(iter->second); + + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); + + // Deref the DOM object. + derefObject(type, domObject); + + // Clear the JS wrapper. + v8Object.Dispose(); + } + domMap.impl().clear(); + } + +} // namespace WebCore + +#endif // DOMData_h diff --git a/WebCore/bindings/v8/DOMDataStore.cpp b/WebCore/bindings/v8/DOMDataStore.cpp new file mode 100644 index 0000000..a76ca53 --- /dev/null +++ b/WebCore/bindings/v8/DOMDataStore.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DOMDataStore.h" + +#include "DOMData.h" + +namespace WebCore { + +// DOM binding algorithm: +// +// There are two kinds of DOM objects: +// 1. DOM tree nodes, such as Document, HTMLElement, ... +// there classes implement TreeShared<T> interface; +// 2. Non-node DOM objects, such as CSSRule, Location, etc. +// these classes implement a ref-counted scheme. +// +// A DOM object may have a JS wrapper object. If a tree node +// is alive, its JS wrapper must be kept alive even it is not +// reachable from JS roots. +// However, JS wrappers of non-node objects can go away if +// not reachable from other JS objects. It works like a cache. +// +// DOM objects are ref-counted, and JS objects are traced from +// a set of root objects. They can create a cycle. To break +// cycles, we do following: +// Handles from DOM objects to JS wrappers are always weak, +// so JS wrappers of non-node object cannot create a cycle. +// Before starting a global GC, we create a virtual connection +// between nodes in the same tree in the JS heap. If the wrapper +// of one node in a tree is alive, wrappers of all nodes in +// the same tree are considered alive. This is done by creating +// object groups in GC prologue callbacks. The mark-compact +// collector will remove these groups after each GC. +// +// DOM objects should be deref-ed from the owning thread, not the GC thread +// that does not own them. In V8, GC can kick in from any thread. To ensure +// that DOM objects are always deref-ed from the owning thread when running +// V8 in multi-threading environment, we do following: +// 1. Maintain a thread specific DOM wrapper map for each object map. +// (We're using TLS support from WTF instead of base since V8Bindings +// does not depend on base. We further assume that all child threads +// running V8 instances are created by WTF and thus a destructor will +// be called to clean up all thread specific data.) +// 2. When GC happens: +// 2.1. If the dead object is in GC thread's map, remove the JS reference +// and deref the DOM object. +// 2.2. Otherwise, go through all thread maps to find the owning thread. +// Remove the JS reference from the owning thread's map and move the +// DOM object to a delayed queue. Post a task to the owning thread +// to have it deref-ed from the owning thread at later time. +// 3. When a thread is tearing down, invoke a cleanup routine to go through +// all objects in the delayed queue and the thread map and deref all of +// them. + + +DOMDataStore::DOMDataStore(DOMData* domData) + : m_domNodeMap(0) + , m_domObjectMap(0) + , m_activeDomObjectMap(0) +#if ENABLE(SVG) + , m_domSvgElementInstanceMap(0) + , m_domSvgObjectWithContextMap(0) +#endif + , m_domData(domData) +{ + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataStore::allStores().append(this); +} + +DOMDataStore::~DOMDataStore() +{ + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataStore::allStores().remove(DOMDataStore::allStores().find(this)); +} + +DOMDataList& DOMDataStore::allStores() +{ + DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ()); + return staticDOMDataList; +} + +WTF::Mutex& DOMDataStore::allStoresMutex() +{ + DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ()); + return staticDOMDataListMutex; +} + +void DOMDataStore::forgetDelayedObject(DOMData* domData, void* object) +{ + domData->forgetDelayedObject(object); +} + +void* DOMDataStore::getDOMWrapperMap(DOMWrapperMapType type) +{ + switch (type) { + case DOMNodeMap: + return m_domNodeMap; + case DOMObjectMap: + return m_domObjectMap; + case ActiveDOMObjectMap: + return m_activeDomObjectMap; +#if ENABLE(SVG) + case DOMSVGElementInstanceMap: + return m_domSvgElementInstanceMap; + case DOMSVGObjectWithContextMap: + return m_domSvgObjectWithContextMap; +#endif + } + + ASSERT_NOT_REACHED(); + return 0; +} + +// Called when the object is near death (not reachable from JS roots). +// It is time to remove the entry from the table and dispose the handle. +void DOMDataStore::weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + v8::HandleScope scope; + ASSERT(v8Object->IsObject()); + DOMData::handleWeakObject(DOMDataStore::DOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); +} + +void DOMDataStore::weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + v8::HandleScope scope; + ASSERT(v8Object->IsObject()); + DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); +} + +void DOMDataStore::weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + ASSERT(WTF::isMainThread()); + + Node* node = static_cast<Node*>(domObject); + + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + HashMap<Node*, v8::Object*>& domMapImpl = store->domNodeMap().impl(); + HashMap<Node*, v8::Object*>::iterator it = domMapImpl.find(node); + if (it == domMapImpl.end() || it->second != *v8Object) + continue; + ASSERT(store->domData()->owningThread() == WTF::currentThread()); + v8Object.Dispose(); + domMapImpl.remove(it); + node->deref(); // Nobody overrides Node::deref so it's safe + break; // There might be at most one wrapper for the node in world's maps + } +} + +#if ENABLE(SVG) + +void DOMDataStore::weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + v8::HandleScope scope; + ASSERT(v8Object->IsObject()); + DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Handle<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject)); +} + +void DOMDataStore::weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + v8::HandleScope scope; + ASSERT(v8Object->IsObject()); + DOMData::handleWeakObject(DOMDataStore::DOMSVGObjectWithContextMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); +} + +#endif // ENABLE(SVG) + +} // namespace WebCore diff --git a/WebCore/bindings/v8/DOMDataStore.h b/WebCore/bindings/v8/DOMDataStore.h new file mode 100644 index 0000000..b127089 --- /dev/null +++ b/WebCore/bindings/v8/DOMDataStore.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DOMDataStore_h +#define DOMDataStore_h + +#include "DOMObjectsInclude.h" + +#include <v8.h> +#include <wtf/HashMap.h> +#include <wtf/MainThread.h> +#include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> +#include <wtf/StdLibExtras.h> +#include <wtf/Threading.h> +#include <wtf/ThreadSpecific.h> +#include <wtf/Vector.h> + +namespace WebCore { + + class DOMData; + + typedef WTF::Vector<DOMDataStore*> DOMDataList; + + // DOMDataStore + // + // DOMDataStore is the backing store that holds the maps between DOM objects + // and JavaScript objects. In general, each thread can have multiple backing + // stores, one per isolated world. + // + // This class doesn't manage the lifetime of the store. The data store + // lifetime is managed by subclasses. + // + class DOMDataStore : public Noncopyable { + public: + enum DOMWrapperMapType { + DOMNodeMap, + DOMObjectMap, + ActiveDOMObjectMap, +#if ENABLE(SVG) + DOMSVGElementInstanceMap, + DOMSVGObjectWithContextMap +#endif + }; + + template <class KeyType> + class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> { + public: + InternalDOMWrapperMap(DOMData* domData, v8::WeakReferenceCallback callback) + : DOMWrapperMap<KeyType>(callback), m_domData(domData) { } + + virtual void forget(KeyType* object) + { + DOMWrapperMap<KeyType>::forget(object); + forgetDelayedObject(m_domData, object); + } + + void forgetOnly(KeyType* object) { DOMWrapperMap<KeyType>::forget(object); } + + private: + DOMData* m_domData; + }; + + DOMDataStore(DOMData*); + virtual ~DOMDataStore(); + + // A list of all DOMDataStore objects. Traversed during GC to find a thread-specific map that + // contains the object - so we can schedule the object to be deleted on the thread which created it. + static DOMDataList& allStores(); + // Mutex to protect against concurrent access of DOMDataList. + static WTF::Mutex& allStoresMutex(); + + // Helper function to avoid circular includes. + static void forgetDelayedObject(DOMData*, void* object); + + DOMData* domData() const { return m_domData; } + + void* getDOMWrapperMap(DOMWrapperMapType); + + InternalDOMWrapperMap<Node>& domNodeMap() { return *m_domNodeMap; } + InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } + InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; } +#if ENABLE(SVG) + InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; } + InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; } +#endif + + // Need by V8GCController. + static void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); + + protected: + static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject); + static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); +#if ENABLE(SVG) + static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject); + // SVG non-node elements may have a reference to a context node which should be notified when the element is change. + static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject); +#endif + + InternalDOMWrapperMap<Node>* m_domNodeMap; + InternalDOMWrapperMap<void>* m_domObjectMap; + InternalDOMWrapperMap<void>* m_activeDomObjectMap; +#if ENABLE(SVG) + InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap; + InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap; +#endif + + private: + // A back-pointer to the DOMData to which we belong. + DOMData* m_domData; + }; + +} // namespace WebCore + +#endif // DOMDataStore_h diff --git a/WebCore/bindings/v8/DOMObjectsInclude.h b/WebCore/bindings/v8/DOMObjectsInclude.h new file mode 100644 index 0000000..63464db --- /dev/null +++ b/WebCore/bindings/v8/DOMObjectsInclude.h @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DOMObjectsInclude_h +#define DOMObjectsInclude_h + +#include "AbstractWorker.h" +#include "BarInfo.h" +#include "CanvasGradient.h" +#include "CanvasPattern.h" +#include "CanvasPixelArray.h" +#include "CanvasRenderingContext2D.h" +#include "CanvasStyle.h" +#include "CharacterData.h" +#include "ClientRect.h" +#include "ClientRectList.h" +#include "Clipboard.h" +#include "Console.h" +#include "Counter.h" +#include "CSSCharsetRule.h" +#include "CSSFontFaceRule.h" +#include "CSSImportRule.h" +#include "CSSMediaRule.h" +#include "CSSPageRule.h" +#include "CSSRule.h" +#include "CSSRuleList.h" +#include "CSSStyleDeclaration.h" +#include "CSSStyleRule.h" +#include "CSSStyleSheet.h" +#include "CSSValueList.h" +#include "CSSVariablesDeclaration.h" +#include "CSSVariablesRule.h" +#include "Database.h" +#include "DocumentType.h" +#include "DocumentFragment.h" +#include "DOMCoreException.h" +#include "DOMImplementation.h" +#include "DOMParser.h" +#include "DOMSelection.h" +#include "DOMWindow.h" +#include "Entity.h" +#include "ErrorEvent.h" +#include "EventListener.h" +#include "EventTarget.h" +#include "Event.h" +#include "EventException.h" +#include "ExceptionCode.h" +#include "File.h" +#include "FileList.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameTree.h" +#include "History.h" +#include "HTMLNames.h" +#include "HTMLDocument.h" +#include "HTMLElement.h" +#include "HTMLImageElement.h" +#include "HTMLInputElement.h" +#include "HTMLSelectElement.h" +#include "HTMLOptionsCollection.h" +#include "ImageData.h" +#include "InspectorBackend.h" +#include "KeyboardEvent.h" +#include "Location.h" +#include "Media.h" +#include "MediaError.h" +#include "MediaList.h" +#include "MediaPlayer.h" +#include "MessageChannel.h" +#include "MessageEvent.h" +#include "MessagePort.h" +#include "MimeTypeArray.h" +#include "MouseEvent.h" +#include "MutationEvent.h" +#include "Navigator.h" // for MimeTypeArray +#include "NodeFilter.h" +#include "Notation.h" +#include "NodeList.h" +#include "NodeIterator.h" +#include "OverflowEvent.h" +#include "Page.h" +#include "Plugin.h" +#include "PluginArray.h" +#include "ProcessingInstruction.h" +#include "ProgressEvent.h" +#include "Range.h" +#include "RangeException.h" +#include "Rect.h" +#include "RGBColor.h" +#include "Screen.h" +#include "ScriptExecutionContext.h" +#include "SecurityOrigin.h" +#include "Settings.h" +#include "SharedWorker.h" +#include "SharedWorkerContext.h" +#include "SQLTransaction.h" +#include "SQLResultSet.h" +#include "SQLResultSetRowList.h" +#include "StyleSheet.h" +#include "StyleSheetList.h" +#include "SVGColor.h" +#include "SVGPaint.h" +#include "TextEvent.h" +#include "TextMetrics.h" +#include "TimeRanges.h" +#include "TreeWalker.h" +#include "XSLTProcessor.h" +#include "V8AbstractEventListener.h" +#include "V8CustomEventListener.h" +#include "V8DOMWindow.h" +#include "V8HTMLElement.h" +#include "V8LazyEventListener.h" +#include "V8NodeFilterCondition.h" +#include "V8ObjectEventListener.h" +#include "ValidityState.h" +#include "WebKitAnimationEvent.h" +#include "WebKitCSSKeyframeRule.h" +#include "WebKitCSSKeyframesRule.h" +#include "WebKitCSSMatrix.h" +#include "WebKitCSSTransformValue.h" +#include "WebKitPoint.h" +#include "WebKitTransitionEvent.h" +#include "WheelEvent.h" +#include "XMLHttpRequest.h" +#include "XMLHttpRequestException.h" +#include "XMLHttpRequestProgressEvent.h" +#include "XMLHttpRequestUpload.h" +#include "XMLSerializer.h" +#include "XPathException.h" +#include "XPathExpression.h" +#include "XPathNSResolver.h" +#include "XPathResult.h" + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "DOMApplicationCache.h" +#endif + +#if ENABLE(DATAGRID) +#include "DataGridColumn.h" +#include "DataGridColumnList.h" +#endif // DATAGRID + +#if ENABLE(DOM_STORAGE) +#include "Storage.h" +#include "StorageEvent.h" +#endif // DOM_STORAGE + +#if ENABLE(SVG) +#include "SVGAngle.h" +#include "SVGAnimatedPoints.h" +#include "SVGElement.h" +#include "SVGElementInstance.h" +#include "SVGElementInstanceList.h" +#include "SVGException.h" +#include "SVGLength.h" +#include "SVGLengthList.h" +#include "SVGNumberList.h" +#include "SVGPathSeg.h" +#include "SVGPathSegArc.h" +#include "SVGPathSegClosePath.h" +#include "SVGPathSegCurvetoCubic.h" +#include "SVGPathSegCurvetoCubicSmooth.h" +#include "SVGPathSegCurvetoQuadratic.h" +#include "SVGPathSegCurvetoQuadraticSmooth.h" +#include "SVGPathSegLineto.h" +#include "SVGPathSegLinetoHorizontal.h" +#include "SVGPathSegLinetoVertical.h" +#include "SVGPathSegList.h" +#include "SVGPathSegMoveto.h" +#include "SVGPointList.h" +#include "SVGPreserveAspectRatio.h" +#include "SVGRenderingIntent.h" +#include "SVGStringList.h" +#include "SVGTransform.h" +#include "SVGTransformList.h" +#include "SVGUnitTypes.h" +#include "SVGURIReference.h" +#include "SVGZoomEvent.h" +#include "V8SVGPODTypeWrapper.h" +#endif // SVG + +#if ENABLE(WORKERS) +#include "DedicatedWorkerContext.h" +#include "Worker.h" +#include "WorkerContext.h" +#include "WorkerLocation.h" +#include "WorkerNavigator.h" +#endif // WORKERS + +#if ENABLE(XPATH) +#include "XPathEvaluator.h" +#endif // XPATH + +namespace WebCore { + + // A helper class for undetectable document.all + class HTMLAllCollection : public HTMLCollection { + }; + +} // namespace WebCore + +#endif // DOMObjectsInclude_h diff --git a/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp new file mode 100644 index 0000000..4962a92 --- /dev/null +++ b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2009, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This source file coalesces the HTML elements into a single object file to +// reduce bloat and allow us to link release builds on 32-bit Windows. + +#include "bindings/V8AbstractWorker.cpp" +#include "bindings/V8Attr.cpp" +#include "bindings/V8BarInfo.cpp" +#include "bindings/V8CanvasGradient.cpp" +#include "bindings/V8CanvasPattern.cpp" +#include "bindings/V8CanvasPixelArray.cpp" +#include "bindings/V8CanvasRenderingContext2D.cpp" +#include "bindings/V8CDATASection.cpp" +#include "bindings/V8CharacterData.cpp" +#include "bindings/V8ClientRect.cpp" +#include "bindings/V8ClientRectList.cpp" +#include "bindings/V8Clipboard.cpp" +#include "bindings/V8Comment.cpp" +#include "bindings/V8Console.cpp" +#include "bindings/V8Counter.cpp" +#include "bindings/V8CSSCharsetRule.cpp" +#include "bindings/V8CSSFontFaceRule.cpp" +#include "bindings/V8CSSImportRule.cpp" +#include "bindings/V8CSSMediaRule.cpp" +#include "bindings/V8CSSPageRule.cpp" +#include "bindings/V8CSSPrimitiveValue.cpp" +#include "bindings/V8CSSRule.cpp" +#include "bindings/V8CSSRuleList.cpp" +#include "bindings/V8CSSStyleDeclaration.cpp" +#include "bindings/V8CSSStyleRule.cpp" +#include "bindings/V8CSSStyleSheet.cpp" +#include "bindings/V8CSSValue.cpp" +#include "bindings/V8CSSValueList.cpp" +#include "bindings/V8CSSVariablesDeclaration.cpp" +#include "bindings/V8CSSVariablesRule.cpp" +#include "bindings/V8Database.cpp" +#include "bindings/V8DataGridColumn.cpp" +#include "bindings/V8DataGridColumnList.cpp" +#include "bindings/V8DedicatedWorkerContext.cpp" +#include "bindings/V8Document.cpp" +#include "bindings/V8DocumentFragment.cpp" +#include "bindings/V8DocumentType.cpp" +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "bindings/V8DOMApplicationCache.cpp" +#endif +#include "bindings/V8DOMCoreException.cpp" +#include "bindings/V8DOMImplementation.cpp" +#include "bindings/V8DOMParser.cpp" +#include "bindings/V8DOMSelection.cpp" +#include "bindings/V8DOMWindow.cpp" +#include "bindings/V8Element.cpp" +#include "bindings/V8Entity.cpp" +#include "bindings/V8EntityReference.cpp" +#include "bindings/V8ErrorEvent.cpp" +#include "bindings/V8Event.cpp" +#include "bindings/V8EventException.cpp" +#include "bindings/V8File.cpp" +#include "bindings/V8FileList.cpp" +#include "bindings/V8History.cpp" +#include "bindings/V8HTMLAllCollection.cpp" +#include "bindings/V8HTMLAnchorElement.cpp" +#include "bindings/V8HTMLAppletElement.cpp" +#include "bindings/V8HTMLAreaElement.cpp" +#include "bindings/V8HTMLAudioElement.cpp" +#include "bindings/V8HTMLBaseElement.cpp" +#include "bindings/V8HTMLBaseFontElement.cpp" +#include "bindings/V8HTMLBlockquoteElement.cpp" +#include "bindings/V8HTMLBodyElement.cpp" +#include "bindings/V8HTMLBRElement.cpp" +#include "bindings/V8HTMLButtonElement.cpp" +#include "bindings/V8HTMLCanvasElement.cpp" +#include "bindings/V8HTMLCollection.cpp" +#include "bindings/V8HTMLDataGridCellElement.cpp" +#include "bindings/V8HTMLDataGridColElement.cpp" +#include "bindings/V8HTMLDataGridElement.cpp" +#include "bindings/V8HTMLDataGridRowElement.cpp" +#include "bindings/V8HTMLDirectoryElement.cpp" +#include "bindings/V8HTMLDivElement.cpp" +#include "bindings/V8HTMLDListElement.cpp" +#include "bindings/V8HTMLDocument.cpp" +#include "bindings/V8HTMLElement.cpp" +#include "bindings/V8HTMLEmbedElement.cpp" +#include "bindings/V8HTMLFieldSetElement.cpp" +#include "bindings/V8HTMLFontElement.cpp" +#include "bindings/V8HTMLFormElement.cpp" +#include "bindings/V8HTMLFrameElement.cpp" +#include "bindings/V8HTMLFrameSetElement.cpp" +#include "bindings/V8HTMLHeadElement.cpp" +#include "bindings/V8HTMLHeadingElement.cpp" +#include "bindings/V8HTMLHRElement.cpp" +#include "bindings/V8HTMLHtmlElement.cpp" +#include "bindings/V8HTMLIFrameElement.cpp" +#include "bindings/V8HTMLImageElement.cpp" +#include "bindings/V8HTMLInputElement.cpp" +#include "bindings/V8HTMLIsIndexElement.cpp" +#include "bindings/V8HTMLLabelElement.cpp" +#include "bindings/V8HTMLLegendElement.cpp" +#include "bindings/V8HTMLLIElement.cpp" +#include "bindings/V8HTMLLinkElement.cpp" +#include "bindings/V8HTMLMapElement.cpp" +#include "bindings/V8HTMLMarqueeElement.cpp" +#include "bindings/V8HTMLMediaElement.cpp" +#include "bindings/V8HTMLMenuElement.cpp" +#include "bindings/V8HTMLMetaElement.cpp" +#include "bindings/V8HTMLModElement.cpp" +#include "bindings/V8HTMLObjectElement.cpp" +#include "bindings/V8HTMLOListElement.cpp" +#include "bindings/V8HTMLOptGroupElement.cpp" +#include "bindings/V8HTMLOptionElement.cpp" +#include "bindings/V8HTMLOptionsCollection.cpp" +#include "bindings/V8HTMLParagraphElement.cpp" +#include "bindings/V8HTMLParamElement.cpp" +#include "bindings/V8HTMLPreElement.cpp" +#include "bindings/V8HTMLQuoteElement.cpp" +#include "bindings/V8HTMLScriptElement.cpp" +#include "bindings/V8HTMLSelectElement.cpp" +#include "bindings/V8HTMLSourceElement.cpp" +#include "bindings/V8HTMLStyleElement.cpp" +#include "bindings/V8HTMLTableCaptionElement.cpp" +#include "bindings/V8HTMLTableCellElement.cpp" +#include "bindings/V8HTMLTableColElement.cpp" +#include "bindings/V8HTMLTableElement.cpp" +#include "bindings/V8HTMLTableRowElement.cpp" +#include "bindings/V8HTMLTableSectionElement.cpp" +#include "bindings/V8HTMLTextAreaElement.cpp" +#include "bindings/V8HTMLTitleElement.cpp" +#include "bindings/V8HTMLUListElement.cpp" +#include "bindings/V8HTMLVideoElement.cpp" +#include "bindings/V8ImageData.cpp" +#include "bindings/V8InspectorBackend.cpp" +#include "bindings/V8KeyboardEvent.cpp" +#include "bindings/V8Location.cpp" +#include "bindings/V8Media.cpp" +#include "bindings/V8MediaError.cpp" +#include "bindings/V8MediaList.cpp" +#include "bindings/V8MessageChannel.cpp" +#include "bindings/V8MessageEvent.cpp" +#include "bindings/V8MessagePort.cpp" +#include "bindings/V8MimeType.cpp" +#include "bindings/V8MimeTypeArray.cpp" +#include "bindings/V8MouseEvent.cpp" +#include "bindings/V8MutationEvent.cpp" +#include "bindings/V8NamedNodeMap.cpp" +#include "bindings/V8Navigator.cpp" +#include "bindings/V8Node.cpp" +#include "bindings/V8NodeFilter.cpp" +#include "bindings/V8NodeIterator.cpp" +#include "bindings/V8NodeList.cpp" +#include "bindings/V8Notation.cpp" +#include "bindings/V8OverflowEvent.cpp" +#include "bindings/V8Plugin.cpp" +#include "bindings/V8PluginArray.cpp" +#include "bindings/V8ProcessingInstruction.cpp" +#include "bindings/V8ProgressEvent.cpp" +#include "bindings/V8Range.cpp" +#include "bindings/V8RangeException.cpp" +#include "bindings/V8Rect.cpp" +#include "bindings/V8RGBColor.cpp" +#include "bindings/V8Screen.cpp" +#include "bindings/V8SharedWorker.cpp" +#include "bindings/V8SQLError.cpp" +#include "bindings/V8SQLResultSet.cpp" +#include "bindings/V8SQLResultSetRowList.cpp" +#include "bindings/V8SQLTransaction.cpp" +#if ENABLE(DOM_STORAGE) +#include "bindings/V8Storage.cpp" +#include "bindings/V8StorageEvent.cpp" +#endif +#include "bindings/V8StyleSheet.cpp" +#include "bindings/V8StyleSheetList.cpp" +#include "bindings/V8SVGAElement.cpp" +#include "bindings/V8SVGAltGlyphElement.cpp" +#include "bindings/V8SVGAngle.cpp" +#include "bindings/V8SVGAnimateColorElement.cpp" +#include "bindings/V8SVGAnimatedAngle.cpp" +#include "bindings/V8SVGAnimatedBoolean.cpp" +#include "bindings/V8SVGAnimatedEnumeration.cpp" +#include "bindings/V8SVGAnimatedInteger.cpp" +#include "bindings/V8SVGAnimatedLength.cpp" +#include "bindings/V8SVGAnimatedLengthList.cpp" +#include "bindings/V8SVGAnimatedNumber.cpp" +#include "bindings/V8SVGAnimatedNumberList.cpp" +#include "bindings/V8SVGAnimatedPoints.cpp" +#include "bindings/V8SVGAnimatedPreserveAspectRatio.cpp" +#include "bindings/V8SVGAnimatedRect.cpp" +#include "bindings/V8SVGAnimatedString.cpp" +#include "bindings/V8SVGAnimatedTransformList.cpp" +#include "bindings/V8SVGAnimateElement.cpp" +#include "bindings/V8SVGAnimateTransformElement.cpp" +#include "bindings/V8SVGAnimationElement.cpp" +#include "bindings/V8SVGCircleElement.cpp" +#include "bindings/V8SVGClipPathElement.cpp" +#include "bindings/V8SVGColor.cpp" +#include "bindings/V8SVGCursorElement.cpp" +#include "bindings/V8SVGDefinitionSrcElement.cpp" +#include "bindings/V8SVGDefsElement.cpp" +#include "bindings/V8SVGDescElement.cpp" +#include "bindings/V8SVGDocument.cpp" +#include "bindings/V8SVGElement.cpp" +#include "bindings/V8SVGElementInstance.cpp" +#include "bindings/V8SVGElementInstanceList.cpp" +#include "bindings/V8SVGEllipseElement.cpp" +#include "bindings/V8SVGException.cpp" +#include "bindings/V8SVGFontElement.cpp" +#include "bindings/V8SVGFontFaceElement.cpp" +#include "bindings/V8SVGFontFaceFormatElement.cpp" +#include "bindings/V8SVGFontFaceNameElement.cpp" +#include "bindings/V8SVGFontFaceSrcElement.cpp" +#include "bindings/V8SVGFontFaceUriElement.cpp" +#include "bindings/V8SVGForeignObjectElement.cpp" +#include "bindings/V8SVGGElement.cpp" +#include "bindings/V8SVGGlyphElement.cpp" +#include "bindings/V8SVGGradientElement.cpp" +#include "bindings/V8SVGImageElement.cpp" +#include "bindings/V8SVGLength.cpp" +#include "bindings/V8SVGLengthList.cpp" +#include "bindings/V8SVGLinearGradientElement.cpp" +#include "bindings/V8SVGLineElement.cpp" +#include "bindings/V8SVGMarkerElement.cpp" +#include "bindings/V8SVGMaskElement.cpp" +#include "bindings/V8SVGMatrix.cpp" +#include "bindings/V8SVGMetadataElement.cpp" +#include "bindings/V8SVGMissingGlyphElement.cpp" +#include "bindings/V8SVGNumber.cpp" +#include "bindings/V8SVGNumberList.cpp" +#include "bindings/V8SVGPaint.cpp" +#include "bindings/V8SVGPathElement.cpp" +#include "bindings/V8SVGPathSeg.cpp" +#include "bindings/V8SVGPathSegArcAbs.cpp" +#include "bindings/V8SVGPathSegArcRel.cpp" +#include "bindings/V8SVGPathSegClosePath.cpp" +#include "bindings/V8SVGPathSegCurvetoCubicAbs.cpp" +#include "bindings/V8SVGPathSegCurvetoCubicRel.cpp" +#include "bindings/V8SVGPathSegCurvetoCubicSmoothAbs.cpp" +#include "bindings/V8SVGPathSegCurvetoCubicSmoothRel.cpp" +#include "bindings/V8SVGPathSegCurvetoQuadraticAbs.cpp" +#include "bindings/V8SVGPathSegCurvetoQuadraticRel.cpp" +#include "bindings/V8SVGPathSegCurvetoQuadraticSmoothAbs.cpp" +#include "bindings/V8SVGPathSegCurvetoQuadraticSmoothRel.cpp" +#include "bindings/V8SVGPathSegLinetoAbs.cpp" +#include "bindings/V8SVGPathSegLinetoHorizontalAbs.cpp" +#include "bindings/V8SVGPathSegLinetoHorizontalRel.cpp" +#include "bindings/V8SVGPathSegLinetoRel.cpp" +#include "bindings/V8SVGPathSegLinetoVerticalAbs.cpp" +#include "bindings/V8SVGPathSegLinetoVerticalRel.cpp" +#include "bindings/V8SVGPathSegList.cpp" +#include "bindings/V8SVGPathSegMovetoAbs.cpp" +#include "bindings/V8SVGPathSegMovetoRel.cpp" +#include "bindings/V8SVGPatternElement.cpp" +#include "bindings/V8SVGPoint.cpp" +#include "bindings/V8SVGPointList.cpp" +#include "bindings/V8SVGPolygonElement.cpp" +#include "bindings/V8SVGPolylineElement.cpp" +#include "bindings/V8SVGPreserveAspectRatio.cpp" +#include "bindings/V8SVGRadialGradientElement.cpp" +#include "bindings/V8SVGRect.cpp" +#include "bindings/V8SVGRectElement.cpp" +#include "bindings/V8SVGRenderingIntent.cpp" +#include "bindings/V8SVGScriptElement.cpp" +#include "bindings/V8SVGSetElement.cpp" +#include "bindings/V8SVGStopElement.cpp" +#include "bindings/V8SVGStringList.cpp" +#include "bindings/V8SVGStyleElement.cpp" +#include "bindings/V8SVGSVGElement.cpp" +#include "bindings/V8SVGSwitchElement.cpp" +#include "bindings/V8SVGSymbolElement.cpp" +#include "bindings/V8SVGTextContentElement.cpp" +#include "bindings/V8SVGTextElement.cpp" +#include "bindings/V8SVGTextPathElement.cpp" +#include "bindings/V8SVGTextPositioningElement.cpp" +#include "bindings/V8SVGTitleElement.cpp" +#include "bindings/V8SVGTransform.cpp" +#include "bindings/V8SVGTransformList.cpp" +#include "bindings/V8SVGTRefElement.cpp" +#include "bindings/V8SVGTSpanElement.cpp" +#include "bindings/V8SVGUnitTypes.cpp" +#include "bindings/V8SVGURIReference.cpp" +#include "bindings/V8SVGUseElement.cpp" +#include "bindings/V8SVGViewElement.cpp" +#include "bindings/V8SVGZoomEvent.cpp" +#include "bindings/V8Text.cpp" +#include "bindings/V8TextEvent.cpp" +#include "bindings/V8TextMetrics.cpp" +#include "bindings/V8TimeRanges.cpp" +#include "bindings/V8TreeWalker.cpp" +#include "bindings/V8UIEvent.cpp" +#include "bindings/V8ValidityState.cpp" +#include "bindings/V8WebKitAnimationEvent.cpp" +#include "bindings/V8WebKitCSSKeyframeRule.cpp" +#include "bindings/V8WebKitCSSKeyframesRule.cpp" +#include "bindings/V8WebKitCSSMatrix.cpp" +#include "bindings/V8WebKitCSSTransformValue.cpp" +#include "bindings/V8WebKitPoint.cpp" +#include "bindings/V8WebKitTransitionEvent.cpp" +#include "bindings/V8WheelEvent.cpp" +#include "bindings/V8Worker.cpp" +#include "bindings/V8WorkerContext.cpp" +#include "bindings/V8WorkerLocation.cpp" +#include "bindings/V8WorkerNavigator.cpp" +#include "bindings/V8XMLHttpRequest.cpp" +#include "bindings/V8XMLHttpRequestException.cpp" +#include "bindings/V8XMLHttpRequestProgressEvent.cpp" +#include "bindings/V8XMLHttpRequestUpload.cpp" +#include "bindings/V8XMLSerializer.cpp" +#include "bindings/V8XPathEvaluator.cpp" +#include "bindings/V8XPathException.cpp" +#include "bindings/V8XPathExpression.cpp" +#include "bindings/V8XPathNSResolver.cpp" +#include "bindings/V8XPathResult.cpp" +#include "bindings/V8XSLTProcessor.cpp" diff --git a/WebCore/bindings/v8/MainThreadDOMData.cpp b/WebCore/bindings/v8/MainThreadDOMData.cpp new file mode 100644 index 0000000..ea34444 --- /dev/null +++ b/WebCore/bindings/v8/MainThreadDOMData.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MainThreadDOMData.h" + +#include "V8IsolatedWorld.h" + +namespace WebCore { + +MainThreadDOMData::MainThreadDOMData() + : m_defaultStore(this) +{ +} + +DOMDataStore& MainThreadDOMData::getStore() +{ + ASSERT(WTF::isMainThread()); + V8IsolatedWorld* world = V8IsolatedWorld::getEntered(); + if (world) + return *world->getDOMDataStore(); + return m_defaultStore; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/MainThreadDOMData.h b/WebCore/bindings/v8/MainThreadDOMData.h new file mode 100644 index 0000000..5c78cec --- /dev/null +++ b/WebCore/bindings/v8/MainThreadDOMData.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MainThreadDOMData_h +#define MainThreadDOMData_h + +#include "DOMData.h" +#include "StaticDOMDataStore.h" + +namespace WebCore { + + class MainThreadDOMData : public DOMData { + public: + MainThreadDOMData(); + DOMDataStore& getStore(); + + private: + StaticDOMDataStore m_defaultStore; + // Note: The DOMDataStores for isolated world are owned by the world object. + }; + +} // namespace WebCore + +#endif // MainThreadDOMData_h diff --git a/WebCore/bindings/v8/NPV8Object.cpp b/WebCore/bindings/v8/NPV8Object.cpp new file mode 100644 index 0000000..15dc852 --- /dev/null +++ b/WebCore/bindings/v8/NPV8Object.cpp @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Google, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "NPV8Object.h" + +#include "ChromiumBridge.h" +#include "DOMWindow.h" +#include "Frame.h" +#include "OwnArrayPtr.h" +#include "PlatformString.h" +#include "ScriptController.h" +#include "V8CustomBinding.h" +#include "V8GCController.h" +#include "V8Helpers.h" +#include "V8NPUtils.h" +#include "V8Proxy.h" +#include "bindings/npruntime.h" +#include "npruntime_impl.h" +#include "npruntime_priv.h" + +#include <stdio.h> +#include <v8.h> +#include <wtf/StringExtras.h> + +using WebCore::toV8Context; +using WebCore::toV8Proxy; +using WebCore::V8ClassIndex; +using WebCore::V8Custom; +using WebCore::V8DOMWrapper; +using WebCore::V8GCController; +using WebCore::V8Proxy; + +// FIXME: Comments on why use malloc and free. +static NPObject* allocV8NPObject(NPP, NPClass*) +{ + return static_cast<NPObject*>(malloc(sizeof(V8NPObject))); +} + +static void freeV8NPObject(NPObject* npObject) +{ + V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(v8NpObject, v8NpObject->v8Object); +#endif + v8NpObject->v8Object.Dispose(); + free(v8NpObject); +} + +static v8::Handle<v8::Value>* createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPObject* owner) +{ + v8::Handle<v8::Value>* argv = new v8::Handle<v8::Value>[argumentCount]; + for (uint32_t index = 0; index < argumentCount; index++) { + const NPVariant* arg = &arguments[index]; + argv[index] = convertNPVariantToV8Object(arg, owner); + } + return argv; +} + +// Create an identifier (null terminated utf8 char*) from the NPIdentifier. +static v8::Local<v8::String> npIdentifierToV8Identifier(NPIdentifier name) +{ + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(name); + if (identifier->isString) + return v8::String::New(static_cast<const char*>(identifier->value.string)); + + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%d", identifier->value.number); + return v8::String::New(buffer); +} + +static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION, + allocV8NPObject, + freeV8NPObject, + 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +// NPAPI's npruntime functions. +NPClass* npScriptObjectClass = &V8NPObjectClass; + +NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore::DOMWindow* root) +{ + // Check to see if this object is already wrapped. + if (object->InternalFieldCount() == V8Custom::kNPObjectInternalFieldCount) { + v8::Local<v8::Value> typeIndex = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + if (typeIndex->IsNumber() && typeIndex->Uint32Value() == V8ClassIndex::NPOBJECT) { + + NPObject* returnValue = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, object); + _NPN_RetainObject(returnValue); + return returnValue; + } + } + + V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass)); + v8npObject->v8Object = v8::Persistent<v8::Object>::New(object); +#ifndef NDEBUG + V8GCController::registerGlobalHandle(WebCore::NPOBJECT, v8npObject, v8npObject->v8Object); +#endif + v8npObject->rootObject = root; + return reinterpret_cast<NPObject*>(v8npObject); +} + +bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) +{ + if (!npObject) + return false; + + if (npObject->_class != npScriptObjectClass) { + if (npObject->_class->invoke) + return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result); + + VOID_TO_NPVARIANT(*result); + return true; + } + + V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); + + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(methodName); + if (!identifier->isString) + return false; + + v8::HandleScope handleScope; + // FIXME: should use the plugin's owner frame as the security context. + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + v8::Context::Scope scope(context); + + if (methodName == _NPN_GetStringIdentifier("eval")) { + if (argumentCount != 1) + return false; + if (arguments[0].type != NPVariantType_String) + return false; + return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result); + } + + v8::Handle<v8::Value> functionObject = v8NpObject->v8Object->Get(v8::String::New(identifier->value.string)); + if (functionObject.IsEmpty() || functionObject->IsNull()) { + NULL_TO_NPVARIANT(*result); + return false; + } + if (functionObject->IsUndefined()) { + VOID_TO_NPVARIANT(*result); + return false; + } + + V8Proxy* proxy = toV8Proxy(npObject); + ASSERT(proxy); + + // Call the function object. + v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionObject); + OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantArgs(arguments, argumentCount, npObject)); + v8::Local<v8::Value> resultObject = proxy->callFunction(function, v8NpObject->v8Object, argumentCount, argv.get()); + + // If we had an error, return false. The spec is a little unclear here, but says "Returns true if the method was + // successfully invoked". If we get an error return value, was that successfully invoked? + if (resultObject.IsEmpty()) + return false; + + convertV8ObjectToNPVariant(resultObject, npObject, result); + return true; +} + +// FIXME: Fix it same as _NPN_Invoke (HandleScope and such). +bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) +{ + if (!npObject) + return false; + + if (npObject->_class != npScriptObjectClass) { + if (npObject->_class->invokeDefault) + return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result); + + VOID_TO_NPVARIANT(*result); + return true; + } + + V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); + + VOID_TO_NPVARIANT(*result); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + v8::Context::Scope scope(context); + + // Lookup the function object and call it. + v8::Handle<v8::Object> functionObject(v8NpObject->v8Object); + if (!functionObject->IsFunction()) + return false; + + v8::Local<v8::Value> resultObject; + v8::Handle<v8::Function> function(v8::Function::Cast(*functionObject)); + if (!function->IsNull()) { + V8Proxy* proxy = toV8Proxy(npObject); + ASSERT(proxy); + + OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantArgs(arguments, argumentCount, npObject)); + resultObject = proxy->callFunction(function, functionObject, argumentCount, argv.get()); + } + // If we had an error, return false. The spec is a little unclear here, but says "Returns true if the method was + // successfully invoked". If we get an error return value, was that successfully invoked? + if (resultObject.IsEmpty()) + return false; + + convertV8ObjectToNPVariant(resultObject, npObject, result); + return true; +} + +bool _NPN_Evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* result) +{ + bool popupsAllowed = WebCore::ChromiumBridge::popupsAllowed(npp); + return _NPN_EvaluateHelper(npp, popupsAllowed, npObject, npScript, result); +} + +bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPString* npScript, NPVariant* result) +{ + VOID_TO_NPVARIANT(*result); + if (!npObject) + return false; + + if (npObject->_class != npScriptObjectClass) + return false; + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + V8Proxy* proxy = toV8Proxy(npObject); + ASSERT(proxy); + + v8::Context::Scope scope(context); + + WebCore::String filename; + if (!popupsAllowed) + filename = "npscript"; + + WebCore::String script = WebCore::String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length); + v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(filename)), 0); + + if (v8result.IsEmpty()) + return false; + + convertV8ObjectToNPVariant(v8result, npObject, result); + return true; +} + +bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(propertyName)); + + convertV8ObjectToNPVariant(v8result, npObject, result); + return true; + } + + if (npObject->_class->hasProperty && npObject->_class->getProperty) { + if (npObject->_class->hasProperty(npObject, propertyName)) + return npObject->_class->getProperty(npObject, propertyName, result); + } + + VOID_TO_NPVARIANT(*result); + return false; +} + +bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + obj->Set(npIdentifierToV8Identifier(propertyName), + convertNPVariantToV8Object(value, object->rootObject->frame()->script()->windowScriptNPObject())); + return true; + } + + if (npObject->_class->setProperty) + return npObject->_class->setProperty(npObject, propertyName, value); + + return false; +} + +bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) +{ + if (!npObject) + return false; + if (npObject->_class != npScriptObjectClass) + return false; + + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + // FIXME: Verify that setting to undefined is right. + obj->Set(npIdentifierToV8Identifier(propertyName), v8::Undefined()); + return true; +} + +bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + return obj->Has(npIdentifierToV8Identifier(propertyName)); + } + + if (npObject->_class->hasProperty) + return npObject->_class->hasProperty(npObject, propertyName); + return false; +} + +bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + v8::Handle<v8::Value> prop = obj->Get(npIdentifierToV8Identifier(methodName)); + return prop->IsFunction(); + } + + if (npObject->_class->hasMethod) + return npObject->_class->hasMethod(npObject, methodName); + return false; +} + +void _NPN_SetException(NPObject* npObject, const NPUTF8 *message) +{ + if (npObject->_class != npScriptObjectClass) + return; + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(0, npObject); + if (context.IsEmpty()) + return; + + v8::Context::Scope scope(context); + V8Proxy::throwError(V8Proxy::GeneralError, message); +} + +bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint32_t* count) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + + // FIXME: http://b/issue?id=1210340: Use a v8::Object::Keys() method when it exists, instead of evaluating javascript. + + // FIXME: Figure out how to cache this helper function. Run a helper function that collects the properties + // on the object into an array. + const char enumeratorCode[] = + "(function (obj) {" + " var props = [];" + " for (var prop in obj) {" + " props[props.length] = prop;" + " }" + " return props;" + "});"; + v8::Handle<v8::String> source = v8::String::New(enumeratorCode); + v8::Handle<v8::Script> script = v8::Script::Compile(source, 0); + v8::Handle<v8::Value> enumeratorObj = script->Run(); + v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(enumeratorObj); + v8::Handle<v8::Value> argv[] = { obj }; + v8::Local<v8::Value> propsObj = enumerator->Call(v8::Handle<v8::Object>::Cast(enumeratorObj), ARRAYSIZE_UNSAFE(argv), argv); + if (propsObj.IsEmpty()) + return false; + + // Convert the results into an array of NPIdentifiers. + v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj); + *count = props->Length(); + *identifier = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier*) * *count)); + for (uint32_t i = 0; i < *count; ++i) { + v8::Local<v8::Value> name = props->Get(v8::Integer::New(i)); + (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(name)); + } + return true; + } + + if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate) + return npObject->_class->enumerate(npObject, identifier, count); + + return false; +} + +bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + // Lookup the constructor function. + v8::Handle<v8::Object> ctorObj(object->v8Object); + if (!ctorObj->IsFunction()) + return false; + + // Call the constructor. + v8::Local<v8::Value> resultObject; + v8::Handle<v8::Function> ctor(v8::Function::Cast(*ctorObj)); + if (!ctor->IsNull()) { + V8Proxy* proxy = toV8Proxy(npObject); + ASSERT(proxy); + + OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantArgs(arguments, argumentCount, npObject)); + resultObject = proxy->newInstance(ctor, argumentCount, argv.get()); + } + + if (resultObject.IsEmpty()) + return false; + + convertV8ObjectToNPVariant(resultObject, npObject, result); + return true; + } + + if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct) + return npObject->_class->construct(npObject, arguments, argumentCount, result); + + return false; +} diff --git a/WebCore/bindings/v8/NPV8Object.h b/WebCore/bindings/v8/NPV8Object.h new file mode 100644 index 0000000..65a7ccf --- /dev/null +++ b/WebCore/bindings/v8/NPV8Object.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NPV8Object_h +#define NPV8Object_h + +#include "bindings/npruntime.h" +#include <v8.h> + +namespace WebCore { + class DOMWindow; +} + +extern NPClass* npScriptObjectClass; + +// A V8NPObject is a NPObject which carries additional V8-specific information. It is allocated and deallocated by +// AllocV8NPObject() and FreeV8NPObject() methods. +struct V8NPObject { + NPObject object; + v8::Persistent<v8::Object> v8Object; + WebCore::DOMWindow* rootObject; +}; + +struct PrivateIdentifier { + union { + const NPUTF8* string; + int32_t number; + } value; + bool isString; +}; + +NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, WebCore::DOMWindow*); + +#endif // NPV8Object_h diff --git a/WebCore/bindings/v8/OwnHandle.h b/WebCore/bindings/v8/OwnHandle.h new file mode 100644 index 0000000..6580674 --- /dev/null +++ b/WebCore/bindings/v8/OwnHandle.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OwnHandle_h +#define OwnHandle_h + +#include <v8.h> + +namespace WebCore { + + template<typename T> + class OwnHandle { + public: + OwnHandle() { } + explicit OwnHandle(v8::Handle<T> handle) : m_handle(v8::Persistent<T>::New(handle)) { } + ~OwnHandle() { clear(); } + + v8::Handle<T> get() const { return m_handle; } + void set(v8::Handle<T> handle) { clear(); m_handle = v8::Persistent<T>::New(handle); } + + // FIXME: What if we release a weak handle? Won't the callback do the wrong thing? + v8::Persistent<T> release() { v8::Persistent<T> result = m_handle; m_handle.Clear(); return result; } + void adopt(v8::Persistent<T> handle) { clear(); m_handle = handle; } + + // Note: This is clear in the OwnPtr sense, not the v8::Handle sense. + void clear() + { + if (m_handle.IsEmpty()) + return; + m_handle.Dispose(); + m_handle.Clear(); + } + + // Make the underlying handle weak. The client doesn't get a callback, + // we just make the handle empty. + void makeWeak() + { + if (m_handle.IsEmpty()) + return; + m_handle.MakeWeak(this, &OwnHandle<T>::weakCallback); + } + + private: + static void weakCallback(v8::Persistent<v8::Value> object, void* ownHandle) + { + OwnHandle<T>* handle = static_cast<OwnHandle<T>*>(ownHandle); + handle->clear(); + } + + v8::Persistent<T> m_handle; + }; + +} // namespace WebCore + +#endif // OwnHandle_h diff --git a/WebCore/bindings/v8/ScheduledAction.cpp b/WebCore/bindings/v8/ScheduledAction.cpp index b1db8cf..44e8a37 100644 --- a/WebCore/bindings/v8/ScheduledAction.cpp +++ b/WebCore/bindings/v8/ScheduledAction.cpp @@ -50,7 +50,7 @@ ScheduledAction::ScheduledAction(v8::Handle<v8::Function> func, int argc, v8::Ha m_function = v8::Persistent<v8::Function>::New(func); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCHEDULED_ACTION, this, m_function); + V8GCController::registerGlobalHandle(SCHEDULED_ACTION, this, m_function); #endif m_argc = argc; @@ -60,7 +60,7 @@ ScheduledAction::ScheduledAction(v8::Handle<v8::Function> func, int argc, v8::Ha m_argv[i] = v8::Persistent<v8::Value>::New(argv[i]); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCHEDULED_ACTION, this, m_argv[i]); + V8GCController::registerGlobalHandle(SCHEDULED_ACTION, this, m_argv[i]); #endif } } else @@ -73,13 +73,13 @@ ScheduledAction::~ScheduledAction() return; #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_function); + V8GCController::unregisterGlobalHandle(this, m_function); #endif m_function.Dispose(); for (int i = 0; i < m_argc; i++) { #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_argv[i]); + V8GCController::unregisterGlobalHandle(this, m_argv[i]); #endif m_argv[i].Dispose(); } @@ -107,7 +107,7 @@ void ScheduledAction::execute(V8Proxy* proxy) LOCK_V8; v8::HandleScope handleScope; - v8::Local<v8::Context> v8Context = proxy->GetContext(); + v8::Local<v8::Context> v8Context = proxy->context(); if (v8Context.IsEmpty()) return; // JS may not be enabled. @@ -117,7 +117,7 @@ void ScheduledAction::execute(V8Proxy* proxy) // FIXME: Need to implement timeouts for preempting a long-running script. if (!m_function.IsEmpty() && m_function->IsFunction()) { - proxy->CallFunction(v8::Persistent<v8::Function>::Cast(m_function), v8Context->Global(), m_argc, m_argv); + proxy->callFunction(v8::Persistent<v8::Function>::Cast(m_function), v8Context->Global(), m_argc, m_argv); Document::updateStyleForAllDocuments(); } else proxy->evaluate(m_code, 0); @@ -136,7 +136,7 @@ void ScheduledAction::execute(WorkerContext* workerContext) if (!m_function.IsEmpty() && m_function->IsFunction()) { LOCK_V8; v8::HandleScope handleScope; - v8::Local<v8::Context> v8Context = scriptController->proxy()->GetContext(); + v8::Local<v8::Context> v8Context = scriptController->proxy()->context(); ASSERT(!v8Context.IsEmpty()); v8::Context::Scope scope(v8Context); m_function->Call(v8Context->Global(), m_argc, m_argv); diff --git a/WebCore/bindings/v8/ScopedDOMDataStore.cpp b/WebCore/bindings/v8/ScopedDOMDataStore.cpp new file mode 100644 index 0000000..19cd545 --- /dev/null +++ b/WebCore/bindings/v8/ScopedDOMDataStore.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScopedDOMDataStore.h" + +namespace WebCore { + +ScopedDOMDataStore::ScopedDOMDataStore(DOMData* domData) + : DOMDataStore(domData) +{ + m_domNodeMap = new InternalDOMWrapperMap<Node>(domData, &DOMDataStore::weakNodeCallback); + m_domObjectMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakDOMObjectCallback); + m_activeDomObjectMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakActiveDOMObjectCallback); +#if ENABLE(SVG) + m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstance>(domData, &DOMDataStore::weakSVGElementInstanceCallback); + m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakSVGObjectWithContextCallback); +#endif +} + +ScopedDOMDataStore::~ScopedDOMDataStore() +{ + delete m_domNodeMap; + delete m_domObjectMap; + delete m_activeDomObjectMap; +#if ENABLE(SVG) + delete m_domSvgElementInstanceMap; + delete m_domSvgObjectWithContextMap; +#endif +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ScopedDOMDataStore.h b/WebCore/bindings/v8/ScopedDOMDataStore.h new file mode 100644 index 0000000..c63bab0 --- /dev/null +++ b/WebCore/bindings/v8/ScopedDOMDataStore.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScopedDOMDataStore_h +#define ScopedDOMDataStore_h + +#include "DOMDataStore.h" + +namespace WebCore { + + // ScopedDOMDataStore + // + // ScopedDOMDataStore is a DOMDataStore that controls limits the lifetime of + // the store to the lifetime of the object itself. In other words, when the + // ScopedDOMDataStore object is deallocated, the maps that belong to the store + // are deallocated as well. + // + class ScopedDOMDataStore : public DOMDataStore { + public: + ScopedDOMDataStore(DOMData*); + + // This can be called when WTF thread is tearing down. + // We assume that all child threads running V8 instances are created by WTF. + virtual ~ScopedDOMDataStore(); + }; + +} // namespace WebCore + +#endif // ScopedDOMDataStore_h diff --git a/WebCore/bindings/v8/ScriptArray.cpp b/WebCore/bindings/v8/ScriptArray.cpp new file mode 100644 index 0000000..748ee19 --- /dev/null +++ b/WebCore/bindings/v8/ScriptArray.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScriptArray.h" + +#include "ScriptScope.h" +#include "ScriptState.h" + +#include "Document.h" +#include "Frame.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <v8.h> + +namespace WebCore { + +ScriptArray::ScriptArray(ScriptState* scriptState, v8::Handle<v8::Array> v8Array) + : ScriptObject(scriptState, v8Array) +{ +} + +bool ScriptArray::set(unsigned index, const ScriptObject& value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), value.v8Value()); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, const String& value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8String(value)); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, double value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8::Number::New(value)); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, long long value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8::Number::New(value)); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, int value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8::Number::New(value)); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, bool value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8Boolean(value)); + return scope.success(); +} + +unsigned ScriptArray::length() +{ + ScriptScope scope(m_scriptState); + return v8::Array::Cast(*v8Value())->Length(); +} + +ScriptArray ScriptArray::createNew(ScriptState* scriptState) +{ + ScriptScope scope(scriptState); + return ScriptArray(scriptState, v8::Array::New()); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptArray.h b/WebCore/bindings/v8/ScriptArray.h new file mode 100644 index 0000000..6e8f852 --- /dev/null +++ b/WebCore/bindings/v8/ScriptArray.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScriptArray_h +#define ScriptArray_h + +#include "ScriptObject.h" + +#include <v8.h> + +namespace WebCore { + class ScriptState; + + class ScriptArray : public ScriptObject { + public: + ScriptArray(ScriptState* scriptState, v8::Handle<v8::Array>); + virtual ~ScriptArray() {} + + bool set(unsigned index, const ScriptObject&); + bool set(unsigned index, const String&); + bool set(unsigned index, double); + bool set(unsigned index, long long); + bool set(unsigned index, int); + bool set(unsigned index, bool); + unsigned length(); + + static ScriptArray createNew(ScriptState*); + }; +} + +#endif // ScriptArray_h diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index 9188dcf..8eb9478 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -39,7 +39,8 @@ namespace WebCore { ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount) - : m_lastCaller(String(), V8Proxy::GetSourceName(), V8Proxy::GetSourceLineNumber() + 1, arguments, skipArgumentCount) + : m_lastCaller(String(), V8Proxy::sourceName(), V8Proxy::sourceLineNumber() + 1, arguments, skipArgumentCount) + , m_scriptState(new ScriptState(V8Proxy::retrieveFrameForCurrentContext())) { } diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index 2dfd484..9f628c8 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -35,6 +35,7 @@ #include "ScriptState.h" #include "ScriptValue.h" #include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> namespace v8 { class Arguments; @@ -51,10 +52,10 @@ namespace WebCore { // FIXME: implement retrieving and storing call stack trace unsigned size() const { return 1; } - // FIXME: This method is obviously not implemented. - ScriptState* state() const { return 0; } + ScriptState* state() const { return m_scriptState.get(); } private: + OwnPtr<ScriptState> m_scriptState; ScriptCallFrame m_lastCaller; }; diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index eecff45..97a3553 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -47,11 +47,13 @@ #include "Frame.h" #include "Node.h" #include "NotImplemented.h" +#include "npruntime_impl.h" #include "npruntime_priv.h" #include "NPV8Object.h" #include "ScriptSourceCode.h" #include "ScriptState.h" #include "Widget.h" +#include "XSSAuditor.h" #include "V8Binding.h" #include "V8NPObject.h" @@ -76,17 +78,17 @@ Frame* ScriptController::retrieveFrameForCurrentContext() bool ScriptController::isSafeScript(Frame* target) { - return V8Proxy::CanAccessFrame(target, true); + return V8Proxy::canAccessFrame(target, true); } void ScriptController::gcProtectJSWrapper(void* domObject) { - V8Proxy::GCProtect(domObject); + V8GCController::gcProtect(domObject); } void ScriptController::gcUnprotectJSWrapper(void* domObject) { - V8Proxy::GCUnprotect(domObject); + V8GCController::gcUnprotect(domObject); } ScriptController::ScriptController(Frame* frame) @@ -99,6 +101,7 @@ ScriptController::ScriptController(Frame* frame) #if ENABLE(NETSCAPE_PLUGIN_API) , m_windowScriptNPObject(0) #endif + , m_XSSAuditor(new XSSAuditor(frame)) { } @@ -112,7 +115,7 @@ void ScriptController::clearScriptObjects() PluginObjectMap::iterator it = m_pluginObjects.begin(); for (; it != m_pluginObjects.end(); ++it) { _NPN_UnregisterObject(it->second); - NPN_ReleaseObject(it->second); + _NPN_ReleaseObject(it->second); } m_pluginObjects.clear(); @@ -147,18 +150,18 @@ bool ScriptController::processingUserGesture() const V8Proxy* activeProxy = activeFrame->script()->proxy(); LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(activeFrame); + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(activeFrame); // FIXME: find all cases context can be empty: // 1) JS is disabled; // 2) page is NULL; - if (context.IsEmpty()) + if (v8Context.IsEmpty()) return true; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); - v8::Handle<v8::Object> global = context->Global(); + v8::Handle<v8::Object> global = v8Context->Global(); v8::Handle<v8::Value> jsEvent = global->Get(v8::String::NewSymbol("event")); - Event* event = V8Proxy::ToNativeEvent(jsEvent); + Event* event = V8DOMWrapper::convertToNativeEvent(jsEvent); // Based on code from kjs_bindings.cpp. // Note: This is more liberal than Firefox's implementation. @@ -183,21 +186,41 @@ bool ScriptController::processingUserGesture() const return false; } -void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources) +void ScriptController::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup) { - m_proxy->evaluateInNewContext(sources); + m_proxy->evaluateInNewWorld(sources, extensionGroup); +} + +void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) +{ + m_proxy->evaluateInNewContext(sources, extensionGroup); } // Evaluate a script file in the environment of this proxy. ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { +#ifdef MANUAL_MERGE_REQUIRED LOCK_V8; +#else // MANUAL_MERGE_REQUIRED + String sourceURL = sourceCode.url(); + + if (sourceURL.isNull() && !m_XSSAuditor->canEvaluateJavaScriptURL(sourceCode.source())) { + // This JavaScript URL is not safe to be evaluated. + return ScriptValue(); + } + + if (!sourceURL.isNull() && !m_XSSAuditor->canEvaluate(sourceCode.source())) { + // This script is not safe to be evaluated. + return ScriptValue(); + } + +#endif // MANUAL_MERGE_REQUIRED v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_proxy->frame()); + if (v8Context.IsEmpty()) return ScriptValue(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); RefPtr<Frame> protect(m_frame); @@ -215,7 +238,7 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) void ScriptController::setEventHandlerLineNumber(int lineNumber) { - m_proxy->setEventHandlerLineno(lineNumber); + m_proxy->setEventHandlerLineNumber(lineNumber); } void ScriptController::finishedWithEvent(Event* event) @@ -229,16 +252,16 @@ void ScriptController::bindToWindowObject(Frame* frame, const String& key, NPObj LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); - v8::Handle<v8::Object> value = CreateV8ObjectForNPObject(object, 0); + v8::Handle<v8::Object> value = createV8ObjectForNPObject(object, 0); // Attach to the global object. - v8::Handle<v8::Object> global = context->Global(); + v8::Handle<v8::Object> global = v8Context->Global(); global->Set(v8String(key), value); } @@ -246,18 +269,18 @@ void ScriptController::collectGarbage() { LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_proxy->frame()); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); m_proxy->evaluate(ScriptSourceCode("if (window.gc) void(gc());"), 0); } bool ScriptController::haveInterpreter() const { - return m_proxy->ContextInitialized(); + return m_proxy->isContextInitialized(); } bool ScriptController::isEnabled() const @@ -309,9 +332,9 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge // // Inside the javascript engine, the engine can keep a reference to the // NPObject as part of its wrapper. However, before accessing the object - // it must consult the NPN_Registry. + // it must consult the _NPN_Registry. - v8::Local<v8::Object> wrapper = CreateV8ObjectForNPObject(npObject, 0); + v8::Local<v8::Object> wrapper = createV8ObjectForNPObject(npObject, 0); // Track the plugin object. We've been given a reference to the object. m_pluginObjects.set(widget, npObject); @@ -325,7 +348,7 @@ void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) if (it == m_pluginObjects.end()) return; _NPN_UnregisterObject(it->second); - NPN_ReleaseObject(it->second); + _NPN_ReleaseObject(it->second); m_pluginObjects.remove(it); } @@ -339,13 +362,13 @@ static NPObject* createScriptObject(Frame* frame) { LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); + if (v8Context.IsEmpty()) return createNoScriptObject(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); DOMWindow* window = frame->domWindow(); - v8::Handle<v8::Value> global = V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, window); + v8::Handle<v8::Value> global = V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, window); ASSERT(global->IsObject()); return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(global), window); } @@ -377,13 +400,13 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); + if (v8Context.IsEmpty()) return createNoScriptObject(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); DOMWindow* window = m_frame->domWindow(); - v8::Handle<v8::Value> v8plugin = V8Proxy::ToV8Object(V8ClassIndex::HTMLEMBEDELEMENT, plugin); + v8::Handle<v8::Value> v8plugin = V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLEMBEDELEMENT, plugin); if (!v8plugin->IsObject()) return createNoScriptObject(); diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index 17703b5..47acf35 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -49,6 +49,7 @@ namespace WebCore { class ScriptState; class String; class Widget; + class XSSAuditor; class ScriptController { public: @@ -64,11 +65,17 @@ namespace WebCore { // as a string. ScriptValue evaluate(const ScriptSourceCode&); + // Executes JavaScript in a new world associated with the web frame. The + // script gets its own global scope, its own prototypes for intrinsic + // JavaScript objects (String, Array, and so-on), and its own wrappers for + // all DOM nodes and DOM constructors. + void evaluateInNewWorld(const Vector<ScriptSourceCode>&, int extensionGroup); + // Executes JavaScript in a new context associated with the web frame. The // script gets its own global scope and its own prototypes for intrinsic // JavaScript objects (String, Array, and so-on). It shares the wrappers for // all DOM nodes and DOM constructors. - void evaluateInNewContext(const Vector<ScriptSourceCode>&); + void evaluateInNewContext(const Vector<ScriptSourceCode>&, int extensionGroup); // JSC has a WindowShell object, but for V8, the ScriptController // is the WindowShell. @@ -81,6 +88,8 @@ namespace WebCore { ScriptState* state() const { return m_scriptState.get(); } + XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); } + void collectGarbage(); // Creates a property of the global object of a frame. @@ -160,6 +169,8 @@ namespace WebCore { #if ENABLE(NETSCAPE_PLUGIN_API) NPObject* m_windowScriptNPObject; #endif + // The XSSAuditor associated with this ScriptController. + OwnPtr<XSSAuditor> m_XSSAuditor; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptEventListener.cpp b/WebCore/bindings/v8/ScriptEventListener.cpp index 42c2529..7a8aa64 100644 --- a/WebCore/bindings/v8/ScriptEventListener.cpp +++ b/WebCore/bindings/v8/ScriptEventListener.cpp @@ -34,6 +34,7 @@ #include "Attribute.h" #include "Document.h" #include "Frame.h" +#include "XSSAuditor.h" namespace WebCore { @@ -46,6 +47,11 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, Attribu if (!frame) return 0; + if (!frame->script()->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { + // This script is not safe to execute. + return 0; + } + return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), node->isSVGElement()); } @@ -54,6 +60,11 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attri if (!frame) return 0; + if (!frame->script()->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { + // This script is not safe to execute. + return 0; + } + return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), frame->document()->isSVGDocument()); } diff --git a/WebCore/bindings/v8/ScriptFunctionCall.cpp b/WebCore/bindings/v8/ScriptFunctionCall.cpp index d2f7a52..2fa43d5 100644 --- a/WebCore/bindings/v8/ScriptFunctionCall.cpp +++ b/WebCore/bindings/v8/ScriptFunctionCall.cpp @@ -162,7 +162,7 @@ ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExcept return ScriptObject(); } - return ScriptObject(result); + return ScriptObject(m_scriptState, result); } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptInstance.cpp b/WebCore/bindings/v8/ScriptInstance.cpp index aa4a396..645b1da 100644 --- a/WebCore/bindings/v8/ScriptInstance.cpp +++ b/WebCore/bindings/v8/ScriptInstance.cpp @@ -62,7 +62,7 @@ void V8ScriptInstance::clear() if (m_instance.IsEmpty()) return; #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_instance); + V8GCController::unregisterGlobalHandle(this, m_instance); #endif m_instance.Dispose(); m_instance.Clear(); @@ -76,7 +76,7 @@ void V8ScriptInstance::set(v8::Handle<v8::Object> instance) m_instance = v8::Persistent<v8::Object>::New(instance); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCRIPTINSTANCE, this, m_instance); + V8GCController::registerGlobalHandle(SCRIPTINSTANCE, this, m_instance); #endif } diff --git a/WebCore/bindings/v8/ScriptObject.cpp b/WebCore/bindings/v8/ScriptObject.cpp index 59316f0..c64cfe4 100644 --- a/WebCore/bindings/v8/ScriptObject.cpp +++ b/WebCore/bindings/v8/ScriptObject.cpp @@ -43,8 +43,9 @@ namespace WebCore { -ScriptObject::ScriptObject(v8::Handle<v8::Object> v8Object) +ScriptObject::ScriptObject(ScriptState* scriptState, v8::Handle<v8::Object> v8Object) : ScriptValue(v8Object) + , m_scriptState(scriptState) { } @@ -54,51 +55,51 @@ v8::Local<v8::Object> ScriptObject::v8Object() const return v8::Local<v8::Object>(v8::Object::Cast(*v8Value())); } -bool ScriptObject::set(ScriptState* scriptState, const String& name, const String& value) +bool ScriptObject::set(const String& name, const String& value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8String(name), v8String(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, const ScriptObject& value) +bool ScriptObject::set(const char* name, const ScriptObject& value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), value.v8Value()); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, const String& value) +bool ScriptObject::set(const char* name, const String& value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8String(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, double value) +bool ScriptObject::set(const char* name, double value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8::Number::New(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, long long value) +bool ScriptObject::set(const char* name, long long value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8::Number::New(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, int value) +bool ScriptObject::set(const char* name, int value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8::Number::New(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, bool value) +bool ScriptObject::set(const char* name, bool value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8Boolean(value)); return scope.success(); } @@ -106,7 +107,7 @@ bool ScriptObject::set(ScriptState* scriptState, const char* name, bool value) ScriptObject ScriptObject::createNew(ScriptState* scriptState) { ScriptScope scope(scriptState); - return ScriptObject(v8::Object::New()); + return ScriptObject(scriptState, v8::Object::New()); } bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, const ScriptObject& value) @@ -116,12 +117,16 @@ bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, const S return scope.success(); } -bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorController* value) +bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorBackend* value) { ScriptScope scope(scriptState); +#ifdef MANUAL_MERGE_REQUIRED #if !PLATFORM(ANDROID) scope.global()->Set(v8::String::New(name), V8Proxy::ToV8Object(V8ClassIndex::INSPECTORCONTROLLER, value)); #endif +#else // MANUAL_MERGE_REQUIRED + scope.global()->Set(v8::String::New(name), V8DOMWrapper::convertToV8Object(V8ClassIndex::INSPECTORBACKEND, value)); +#endif // MANUAL_MERGE_REQUIRED return scope.success(); } @@ -135,7 +140,7 @@ bool ScriptGlobalObject::get(ScriptState* scriptState, const char* name, ScriptO if (!v8Value->IsObject()) return false; - value = ScriptObject(v8::Handle<v8::Object>(v8::Object::Cast(*v8Value))); + value = ScriptObject(scriptState, v8::Handle<v8::Object>(v8::Object::Cast(*v8Value))); return true; } diff --git a/WebCore/bindings/v8/ScriptObject.h b/WebCore/bindings/v8/ScriptObject.h index e5618ab..dcee3a5 100644 --- a/WebCore/bindings/v8/ScriptObject.h +++ b/WebCore/bindings/v8/ScriptObject.h @@ -36,32 +36,34 @@ #include <v8.h> namespace WebCore { - class InspectorController; + class InspectorBackend; class ScriptState; class ScriptObject : public ScriptValue { public: - ScriptObject(v8::Handle<v8::Object>); - ScriptObject() {} + ScriptObject(ScriptState*, v8::Handle<v8::Object>); + ScriptObject() {}; virtual ~ScriptObject() {} v8::Local<v8::Object> v8Object() const; - bool set(ScriptState*, const String& name, const String&); - bool set(ScriptState*, const char* name, const ScriptObject&); - bool set(ScriptState*, const char* name, const String&); - bool set(ScriptState*, const char* name, double); - bool set(ScriptState*, const char* name, long long); - bool set(ScriptState*, const char* name, int); - bool set(ScriptState*, const char* name, bool); + bool set(const String& name, const String&); + bool set(const char* name, const ScriptObject&); + bool set(const char* name, const String&); + bool set(const char* name, double); + bool set(const char* name, long long); + bool set(const char* name, int); + bool set(const char* name, bool); static ScriptObject createNew(ScriptState*); + protected: + ScriptState* m_scriptState; }; class ScriptGlobalObject { public: static bool set(ScriptState*, const char* name, const ScriptObject&); - static bool set(ScriptState*, const char* name, InspectorController*); + static bool set(ScriptState*, const char* name, InspectorBackend*); static bool get(ScriptState*, const char* name, ScriptObject&); static bool remove(ScriptState*, const char* name); private: diff --git a/WebCore/bindings/v8/ScriptObjectQuarantine.cpp b/WebCore/bindings/v8/ScriptObjectQuarantine.cpp index 8a7715e..053cf68 100644 --- a/WebCore/bindings/v8/ScriptObjectQuarantine.cpp +++ b/WebCore/bindings/v8/ScriptObjectQuarantine.cpp @@ -66,9 +66,18 @@ bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& qu ASSERT(frame); ASSERT(storage); - // FIXME: Implement when DOM Storage V8 bindings are enabled +#if ENABLE(DOM_STORAGE) + v8::HandleScope handleScope; + v8::Local<v8::Context> context = V8Proxy::context(frame); + // FIXME: What if context.IsEmpty()? + v8::Context::Scope scope(context); + + v8::Handle<v8::Value> v8Storage = V8DOMWrapper::convertToV8Object(V8ClassIndex::STORAGE, storage); + quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8Storage))); +#else ASSERT_NOT_REACHED(); quarantinedObject = ScriptObject(); +#endif return true; } @@ -77,11 +86,15 @@ bool getQuarantinedScriptObject(Node* node, ScriptObject& quarantinedObject) ASSERT(node); v8::HandleScope handleScope; - v8::Local<v8::Context> context = V8Proxy::GetContext(node->document()->page()->mainFrame()); + // FIXME: What if document() is null? + // FIXME: Why are we grabbing the mainFrame? + Frame* frame = node->document()->page()->mainFrame(); + v8::Local<v8::Context> context = V8Proxy::context(frame); + // FIXME: What if context.IsEmpty()? v8::Context::Scope scope(context); - v8::Handle<v8::Value> v8Node = V8Proxy::NodeToV8Object(node); - quarantinedObject = ScriptObject(v8::Local<v8::Object>(v8::Object::Cast(*v8Node))); + v8::Handle<v8::Value> v8Node = V8DOMWrapper::convertNodeToV8Object(node); + quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8Node))); return true; } @@ -91,11 +104,14 @@ bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedO ASSERT(domWindow); v8::HandleScope handleScope; - v8::Local<v8::Context> context = V8Proxy::GetContext(domWindow->frame()); + Frame* frame = domWindow->frame(); + // FIXME: What if frame is null? + v8::Local<v8::Context> context = V8Proxy::context(frame); + // FIXME: What if context.IsEmpty()? v8::Context::Scope scope(context); - v8::Handle<v8::Value> v8DomWindow = V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, domWindow); - quarantinedObject = ScriptObject(v8::Local<v8::Object>(v8::Object::Cast(*v8DomWindow))); + v8::Handle<v8::Value> v8DomWindow = V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow); + quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8DomWindow))); return true; } diff --git a/WebCore/bindings/v8/ScriptScope.cpp b/WebCore/bindings/v8/ScriptScope.cpp index 937f664..52cab10 100644 --- a/WebCore/bindings/v8/ScriptScope.cpp +++ b/WebCore/bindings/v8/ScriptScope.cpp @@ -43,7 +43,7 @@ namespace WebCore { ScriptScope::ScriptScope(ScriptState* scriptState, bool reportExceptions) - : m_context(V8Proxy::GetContext(scriptState->frame())) + : m_context(V8Proxy::context(scriptState->frame())) , m_scope(m_context) , m_scriptState(scriptState) , m_reportExceptions(reportExceptions) diff --git a/WebCore/bindings/v8/ScriptValue.h b/WebCore/bindings/v8/ScriptValue.h index 04e8819..004851b 100644 --- a/WebCore/bindings/v8/ScriptValue.h +++ b/WebCore/bindings/v8/ScriptValue.h @@ -53,7 +53,7 @@ public: m_value = v8::Persistent<v8::Value>::New(value); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCRIPTVALUE, this, m_value); + V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); #endif } @@ -64,7 +64,7 @@ public: m_value = v8::Persistent<v8::Value>::New(value.m_value); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCRIPTVALUE, this, m_value); + V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); #endif } @@ -80,7 +80,7 @@ public: m_value = v8::Persistent<v8::Value>::New(value.m_value); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCRIPTVALUE, this, m_value); + V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); #endif return *this; @@ -122,7 +122,7 @@ public: return; #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_value); + V8GCController::unregisterGlobalHandle(this, m_value); #endif m_value.Dispose(); m_value.Clear(); diff --git a/WebCore/bindings/v8/StaticDOMDataStore.cpp b/WebCore/bindings/v8/StaticDOMDataStore.cpp new file mode 100644 index 0000000..3a02c0b --- /dev/null +++ b/WebCore/bindings/v8/StaticDOMDataStore.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "StaticDOMDataStore.h" + +namespace WebCore { + +StaticDOMDataStore::StaticDOMDataStore(DOMData* domData) + : DOMDataStore(domData) + , m_staticDomNodeMap(domData, &DOMDataStore::weakNodeCallback) + , m_staticDomObjectMap(domData, &DOMDataStore::weakDOMObjectCallback) + , m_staticActiveDomObjectMap(domData, &DOMDataStore::weakActiveDOMObjectCallback) +#if ENABLE(SVG) + , m_staticDomSvgElementInstanceMap(domData, &DOMDataStore::weakSVGElementInstanceCallback) + , m_staticDomSvgObjectWithContextMap(domData, &DOMDataStore::weakSVGObjectWithContextCallback) +#endif +{ + m_domNodeMap = &m_staticDomNodeMap; + m_domObjectMap = &m_staticDomObjectMap; + m_activeDomObjectMap = &m_staticActiveDomObjectMap; +#if ENABLE(SVG) + m_domSvgElementInstanceMap = &m_staticDomSvgElementInstanceMap; + m_domSvgObjectWithContextMap = &m_staticDomSvgObjectWithContextMap; +#endif +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/StaticDOMDataStore.h b/WebCore/bindings/v8/StaticDOMDataStore.h new file mode 100644 index 0000000..4cd0515 --- /dev/null +++ b/WebCore/bindings/v8/StaticDOMDataStore.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef StaticDOMDataStore_h +#define StaticDOMDataStore_h + +#include "DOMDataStore.h" + +namespace WebCore { + +// StaticDOMDataStore +// +// StaticDOMDataStore is a DOMDataStore that manages the lifetime of the store +// statically. This encapsulates thread-specific DOM data for the main +// thread. All the maps in it are static. This is because we are unable to +// rely on WTF::ThreadSpecificThreadExit to do the cleanup since the place that +// tears down the main thread can not call any WTF functions. +// +class StaticDOMDataStore : public DOMDataStore { +public: + StaticDOMDataStore(DOMData*); + +private: + InternalDOMWrapperMap<Node> m_staticDomNodeMap; + InternalDOMWrapperMap<void> m_staticDomObjectMap; + InternalDOMWrapperMap<void> m_staticActiveDomObjectMap; +#if ENABLE(SVG) + InternalDOMWrapperMap<SVGElementInstance> m_staticDomSvgElementInstanceMap; + InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; +#endif +}; + +} // namespace WebCore + +#endif // StaticDOMDataStore_h + diff --git a/WebCore/bindings/v8/V8AbstractEventListener.cpp b/WebCore/bindings/v8/V8AbstractEventListener.cpp index 07e944d..0c81846 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.cpp +++ b/WebCore/bindings/v8/V8AbstractEventListener.cpp @@ -48,6 +48,12 @@ V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute) if (!m_frame) return; + // We might be called directly from the parser. + v8::HandleScope handleScope; + + m_context.set(V8Proxy::context(m_frame)); + m_context.makeWeak(); + // Get the position in the source if any. if (m_isAttribute && m_frame->document()->tokenizer()) { m_lineNumber = m_frame->document()->tokenizer()->lineNumber(); @@ -55,7 +61,7 @@ V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute) } } -void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> context, Event* event, v8::Handle<v8::Value> jsEvent, bool isWindowEvent) +void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> v8Context, Event* event, v8::Handle<v8::Value> jsEvent, bool isWindowEvent) { // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings. v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event"); @@ -67,11 +73,11 @@ void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> context tryCatch.SetVerbose(true); // Save the old 'event' property so we can restore it later. - v8::Local<v8::Value> savedEvent = context->Global()->GetHiddenValue(eventSymbol); + v8::Local<v8::Value> savedEvent = v8Context->Global()->GetHiddenValue(eventSymbol); tryCatch.Reset(); // Make the event available in the global object, so DOMWindow can expose it. - context->Global()->SetHiddenValue(eventSymbol, jsEvent); + v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent); tryCatch.Reset(); // Call the event handler. @@ -80,13 +86,13 @@ void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> context // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) - context->Global()->SetHiddenValue(eventSymbol, v8::Undefined()); + v8Context->Global()->SetHiddenValue(eventSymbol, v8::Undefined()); else - context->Global()->SetHiddenValue(eventSymbol, savedEvent); + v8Context->Global()->SetHiddenValue(eventSymbol, savedEvent); tryCatch.Reset(); } - ASSERT(!V8Proxy::HandleOutOfMemory() || returnValue.IsEmpty()); + ASSERT(!V8Proxy::handleOutOfMemory() || returnValue.IsEmpty()); if (returnValue.IsEmpty()) return; @@ -113,20 +119,20 @@ void V8AbstractEventListener::handleEvent(Event* event, bool isWindowEvent) LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = m_context.get(); + if (v8Context.IsEmpty()) return; // m_frame can removed by the callback function, protect it until the callback function returns. RefPtr<Frame> protectFrame(m_frame); // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); // Get the V8 wrapper for the event object. - v8::Handle<v8::Value> jsEvent = V8Proxy::EventToV8Object(event); + v8::Handle<v8::Value> jsEvent = V8DOMWrapper::convertEventToV8Object(event); - invokeEventHandler(context, event, jsEvent, isWindowEvent); + invokeEventHandler(v8Context, event, jsEvent, isWindowEvent); Document::updateStyleForAllDocuments(); } @@ -135,7 +141,7 @@ void V8AbstractEventListener::disposeListenerObject() { if (!m_listener.IsEmpty()) { #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_listener); + V8GCController::unregisterGlobalHandle(this, m_listener); #endif m_listener.Dispose(); m_listener.Clear(); @@ -151,7 +157,7 @@ v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event, b return v8::Context::GetCurrent()->Global(); EventTarget* target = event->currentTarget(); - v8::Handle<v8::Value> value = V8Proxy::EventTargetToV8Object(target); + v8::Handle<v8::Value> value = V8DOMWrapper::convertEventTargetToV8Object(target); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(v8::Handle<v8::Object>::Cast(value)); diff --git a/WebCore/bindings/v8/V8AbstractEventListener.h b/WebCore/bindings/v8/V8AbstractEventListener.h index ed643db..1521941 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.h +++ b/WebCore/bindings/v8/V8AbstractEventListener.h @@ -32,6 +32,7 @@ #define V8AbstractEventListener_h #include "EventListener.h" +#include "OwnHandle.h" #include <v8.h> namespace WebCore { @@ -39,11 +40,14 @@ namespace WebCore { class Event; class Frame; - // There are two kinds of event listeners: HTML or non-HMTL. onload, onfocus, etc (attributes) are always HTML event handler type; - // Event listeners added by Window.addEventListener or EventTargetNode::addEventListener are non-HTML type. + // There are two kinds of event listeners: HTML or non-HMTL. onload, + // onfocus, etc (attributes) are always HTML event handler type; Event + // listeners added by Window.addEventListener or + // EventTargetNode::addEventListener are non-HTML type. // // Why does this matter? - // WebKit does not allow duplicated HTML event handlers of the same type, but ALLOWs duplicated non-HTML event handlers. + // WebKit does not allow duplicated HTML event handlers of the same type, + // but ALLOWs duplicated non-HTML event handlers. class V8AbstractEventListener : public EventListener { public: virtual ~V8AbstractEventListener() { } @@ -65,6 +69,8 @@ namespace WebCore { virtual bool disconnected() const { return !m_frame; } + virtual bool isObjectListener() const { return false; } + protected: v8::Persistent<v8::Object> m_listener; @@ -83,6 +89,7 @@ namespace WebCore { // deleted. See fast/dom/replaceChild.html // FIXME: this could hold m_frame live until the event listener is deleted. Frame* m_frame; + OwnHandle<v8::Context> m_context; // Position in the HTML source for HTML event listeners. int m_lineNumber; diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp new file mode 100644 index 0000000..c5d580a --- /dev/null +++ b/WebCore/bindings/v8/V8Binding.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8Binding.h" + +#include "AtomicString.h" +#include "CString.h" +#include "MathExtras.h" +#include "PlatformString.h" +#include "StdLibExtras.h" +#include "StringBuffer.h" +#include "StringHash.h" +#include "Threading.h" + +#include <v8.h> + +namespace WebCore { + +// WebCoreStringResource is a helper class for v8ExternalString. It is used +// to manage the life-cycle of the underlying buffer of the external string. +class WebCoreStringResource : public v8::String::ExternalStringResource { +public: + explicit WebCoreStringResource(const String& string) + : m_plainString(string) + { +#ifndef NDEBUG + m_threadId = WTF::currentThread(); +#endif + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + } + + explicit WebCoreStringResource(const AtomicString& string) + : m_plainString(string) + , m_atomicString(string) + { +#ifndef NDEBUG + m_threadId = WTF::currentThread(); +#endif + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + } + + virtual ~WebCoreStringResource() + { +#ifndef NDEBUG + ASSERT(m_threadId == WTF::currentThread()); +#endif + int reducedExternalMemory = -2 * length(); + if (!m_plainString.impl()->inTable()) + reducedExternalMemory *= 2; + v8::V8::AdjustAmountOfExternalAllocatedMemory(reducedExternalMemory); + } + + const uint16_t* data() const + { + return reinterpret_cast<const uint16_t*>(m_plainString.characters()); + } + + size_t length() const { return m_plainString.length(); } + + String webcoreString() { return m_plainString; } + + AtomicString atomicString() + { +#ifndef NDEBUG + ASSERT(m_threadId == WTF::currentThread()); +#endif + if (m_atomicString.isNull()) { + m_atomicString = AtomicString(m_plainString); + if (!m_plainString.impl()->inTable()) + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + } + return m_atomicString; + } + + static WebCoreStringResource* toStringResource(v8::Handle<v8::String> v8String) + { + return static_cast<WebCoreStringResource*>(v8String->GetExternalStringResource()); + } + +private: + // A shallow copy of the string. Keeps the string buffer alive until the V8 engine garbage collects it. + String m_plainString; + // If this string is atomic or has been made atomic earlier the + // atomic string is held here. In the case where the string starts + // off non-atomic and becomes atomic later it is necessary to keep + // the original string alive because v8 may keep derived pointers + // into that string. + AtomicString m_atomicString; + +#ifndef NDEBUG + WTF::ThreadIdentifier m_threadId; +#endif +}; + +String v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external, + StringType type) +{ + WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String); + if (stringResource) + return stringResource->webcoreString(); + + int length = v8String->Length(); + if (!length) { + // Avoid trying to morph empty strings, as they do not have enough room to contain the external reference. + return StringImpl::empty(); + } + + UChar* buffer; + String result = String::createUninitialized(length, buffer); + v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); + + if (type == AtomicStringType) + result = AtomicString(result); + + if (external == Externalize) { + WebCoreStringResource* resource = new WebCoreStringResource(result); + if (!v8String->MakeExternal(resource)) { + // In case of a failure delete the external resource as it was not used. + delete resource; + } + } + return result; +} + +AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String) +{ + WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String); + if (!stringResource) { + // If this string hasn't been externalized, we force it now. + String plain = v8StringToWebCoreString(v8String, Externalize, AtomicStringType); + // If the string is empty there's no room to cache an atomic + // string so we bail out. + if (plain.isEmpty()) + return plain; + stringResource = WebCoreStringResource::toStringResource(v8String); + ASSERT(stringResource != NULL); + } + return stringResource->atomicString(); +} + +String v8ValueToWebCoreString(v8::Handle<v8::Value> object) +{ + if (object->IsString()) + return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(object), Externalize, PlainStringType); + + if (object->IsInt32()) { + int value = object->Int32Value(); + // Most numbers used are <= 100. Even if they aren't used there's very little in using the space. + const int kLowNumbers = 100; + static AtomicString lowNumbers[kLowNumbers + 1]; + String webCoreString; + if (0 <= value && value <= kLowNumbers) { + webCoreString = lowNumbers[value]; + if (!webCoreString) { + AtomicString valueString = AtomicString(String::number(value)); + lowNumbers[value] = valueString; + webCoreString = valueString; + } + } else + webCoreString = String::number(value); + return webCoreString; + } + + v8::TryCatch block; + v8::Handle<v8::String> v8String = object->ToString(); + // Check for empty handles to handle the case where an exception + // is thrown as part of invoking toString on the objectect. + if (v8String.IsEmpty()) + return StringImpl::empty(); + return v8StringToWebCoreString(v8String, DoNotExternalize, PlainStringType); +} + +AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> v8Value) +{ + if (v8Value->IsString()) + return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(v8Value)); + String string = v8ValueToWebCoreString(v8Value); + return AtomicString(string); +} + +v8::Handle<v8::String> v8String(const String& string) +{ + return v8ExternalString(string); +} + +static bool stringImplCacheEnabled = false; + +void enableStringImplCache() +{ + stringImplCacheEnabled = true; +} + +static v8::Local<v8::String> makeExternalString(const String& string) +{ + WebCoreStringResource* stringResource = new WebCoreStringResource(string); + v8::Local<v8::String> newString = v8::String::NewExternal(stringResource); + if (newString.IsEmpty()) + delete stringResource; + + return newString; +} + +typedef HashMap<StringImpl*, v8::String*> StringCache; + +static StringCache& getStringCache() +{ + ASSERT(WTF::isMainThread()); + DEFINE_STATIC_LOCAL(StringCache, mainThreadStringCache, ()); + return mainThreadStringCache; +} + +static void cachedStringCallback(v8::Persistent<v8::Value> wrapper, void* parameter) +{ + ASSERT(WTF::isMainThread()); + StringImpl* stringImpl = static_cast<StringImpl*>(parameter); + ASSERT(getStringCache().contains(stringImpl)); + getStringCache().remove(stringImpl); + wrapper.Dispose(); + stringImpl->deref(); +} + +v8::Local<v8::String> v8ExternalString(const String& string) +{ + if (!string.length()) + return v8::String::Empty(); + + if (!stringImplCacheEnabled) + return makeExternalString(string); + + StringImpl* stringImpl = string.impl(); + StringCache& stringCache = getStringCache(); + v8::String* cachedV8String = stringCache.get(stringImpl); + if (cachedV8String) + return v8::Local<v8::String>(cachedV8String); + + v8::Local<v8::String> newString = makeExternalString(string); + if (newString.IsEmpty()) + return newString; + + v8::Persistent<v8::String> wrapper = v8::Persistent<v8::String>::New(newString); + if (wrapper.IsEmpty()) + return newString; + + stringImpl->ref(); + wrapper.MakeWeak(stringImpl, cachedStringCallback); + stringCache.set(stringImpl, *wrapper); + + return newString; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Binding.h b/WebCore/bindings/v8/V8Binding.h index 9fce3f2..4f36f00 100644 --- a/WebCore/bindings/v8/V8Binding.h +++ b/WebCore/bindings/v8/V8Binding.h @@ -31,16 +31,91 @@ #ifndef V8Binding_h #define V8Binding_h -// FIXME: This is a temporary forwarding header until all bindings have migrated -// over and v8_binding actually becomes V8Binding. -#include "v8_binding.h" +#include "MathExtras.h" +#include "PlatformString.h" + +#include <v8.h> namespace WebCore { - // FIXME: Remove once migration is complete. + enum ExternalMode { + Externalize, + DoNotExternalize + }; + + enum StringType { + PlainStringType, + AtomicStringType + }; + + // Convert v8 types to a WebCore::String. If the V8 string is not already + // an external string then it is transformed into an external string at this + // point to avoid repeated conversions. + String v8StringToWebCoreString(v8::Handle<v8::String>, ExternalMode mode, StringType type); + String v8ValueToWebCoreString(v8::Handle<v8::Value>); + + // Convert v8 types to a WebCore::AtomicString. + AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String>); + AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value>); + + // Convert a string to a V8 string. + v8::Handle<v8::String> v8String(const String&); + + inline String toString(const String& string)
+ {
+ return string;
+ } + + // Return a V8 external string that shares the underlying buffer with the given + // WebCore string. The reference counting mechanism is used to keep the + // underlying buffer alive while the string is still live in the V8 engine. + v8::Local<v8::String> v8ExternalString(const String&); + + // Enables caching v8 wrappers created for WebCore::StringImpl. Currently this cache requires + // all the calls (both to convert WebCore::String to v8::String and to GC the handle) + // to be performed on the main thread. + void enableStringImplCache(); + + // Convert a value to a 32-bit integer. The conversion fails if the + // value cannot be converted to an integer or converts to nan or to an infinity. + inline int toInt32(v8::Handle<v8::Value> value, bool& ok) + { + ok = true; + + // Fast case. The value is already a 32-bit integer. + if (value->IsInt32()) + return value->Int32Value(); + + // Can the value be converted to a number? + v8::Local<v8::Number> numberObject = value->ToNumber(); + if (numberObject.IsEmpty()) { + ok = false; + return 0; + } + + // Does the value convert to nan or to an infinity? + double numberValue = numberObject->Value(); + if (isnan(numberValue) || isinf(numberValue)) { + ok = false; + return 0; + } + + // Can the value be converted to a 32-bit integer? + v8::Local<v8::Int32> intValue = value->ToInt32(); + if (intValue.IsEmpty()) { + ok = false; + return 0; + } + + // Return the result of the int32 conversion. + return intValue->Value(); + } + + // Convert a value to a 32-bit integer assuming the conversion cannot fail. inline int toInt32(v8::Handle<v8::Value> value) { - return ToInt32(value); + bool ok; + return toInt32(value, ok); } inline float toFloat(v8::Local<v8::Value> value) @@ -48,22 +123,17 @@ namespace WebCore { return static_cast<float>(value->NumberValue()); } - // FIXME: Remove once migration is complete. - inline String toWebCoreString(v8::Handle<v8::Value> obj) + // FIXME: Drop this in favor of the type specific v8ValueToWebCoreString when we rework the code generation. + inline String toWebCoreString(v8::Handle<v8::Value> object) { - return ToWebCoreString(obj); + return v8ValueToWebCoreString(object); } - // FIXME: Remove once migration is complete. + // The string returned by this function is still owned by the argument + // and will be deallocated when the argument is deallocated. inline const uint16_t* fromWebCoreString(const String& str) { - return FromWebCoreString(str); - } - - // FIXME: Rename valueToStringWithNullCheck once migration is complete. - inline String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) - { - return valueToStringWithNullCheck(value); + return reinterpret_cast<const uint16_t*>(str.characters()); } inline bool isUndefinedOrNull(v8::Handle<v8::Value> value) @@ -75,7 +145,40 @@ namespace WebCore { { return value ? v8::True() : v8::False(); } + + inline String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) + { + if (value->IsNull()) + return String(); + return v8ValueToWebCoreString(value); + } -} + inline String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value) + { + if (value->IsNull() || value->IsUndefined()) + return String(); + return toWebCoreString(value); + } + + inline v8::Handle<v8::String> v8UndetectableString(const String& str) + { + return v8::String::NewUndetectable(fromWebCoreString(str), str.length()); + } + + inline v8::Handle<v8::Value> v8StringOrNull(const String& str) + { + return str.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(str)); + } + + inline v8::Handle<v8::Value> v8StringOrUndefined(const String& str) + { + return str.isNull() ? v8::Handle<v8::Value>(v8::Undefined()) : v8::Handle<v8::Value>(v8String(str)); + } + + inline v8::Handle<v8::Value> v8StringOrFalse(const String& str) + { + return str.isNull() ? v8::Handle<v8::Value>(v8::False()) : v8::Handle<v8::Value>(v8String(str)); + } +} // namespace WebCore #endif // V8Binding_h diff --git a/WebCore/bindings/v8/V8Collection.cpp b/WebCore/bindings/v8/V8Collection.cpp index 861f68a..c9fc9ac 100644 --- a/WebCore/bindings/v8/V8Collection.cpp +++ b/WebCore/bindings/v8/V8Collection.cpp @@ -48,14 +48,14 @@ v8::Handle<v8::Value> toOptionsCollectionSetter(uint32_t index, v8::Handle<v8::V // Check that the value is an HTMLOptionElement. If not, throw a TYPE_MISMATCH_ERR DOMException. if (!V8HTMLOptionElement::HasInstance(value)) { - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return value; } - HTMLOptionElement* element = V8Proxy::DOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>::Cast(value)); + HTMLOptionElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>::Cast(value)); base->setOption(index, element, ec); - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return value; } diff --git a/WebCore/bindings/v8/V8Collection.h b/WebCore/bindings/v8/V8Collection.h index 1731f9c..cbfe921 100644 --- a/WebCore/bindings/v8/V8Collection.h +++ b/WebCore/bindings/v8/V8Collection.h @@ -47,8 +47,8 @@ namespace WebCore { return v8::Handle<v8::Value>(); V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(implementationType->Int32Value()); if (type == V8ClassIndex::NODE) - return V8Proxy::NodeToV8Object(static_cast<Node*>(implementation)); - return V8Proxy::ToV8Object(type, implementation); + return V8DOMWrapper::convertNodeToV8Object(static_cast<Node*>(implementation)); + return V8DOMWrapper::convertToV8Object(type, implementation); } template<class T> static v8::Handle<v8::Value> getV8Object(PassRefPtr<T> implementation, v8::Local<v8::Value> implementationType) @@ -61,10 +61,10 @@ namespace WebCore { v8::Local<v8::Value> implementationType) { // FIXME: assert object is a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType wrapperType = V8Proxy::GetDOMWrapperType(object); + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(object); ASSERT(wrapperType != V8ClassIndex::NODE); - Collection* collection = V8Proxy::ToNativeObject<Collection>(wrapperType, object); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, object); String propertyName = toWebCoreString(name); return getV8Object<ItemType>(collection->namedItem(propertyName), implementationType); } @@ -87,8 +87,8 @@ namespace WebCore { // A template of named property accessor of HTMLSelectElement and HTMLFormElement. template<class Collection> static v8::Handle<v8::Value> nodeCollectionNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); if (!value.IsEmpty()) @@ -98,7 +98,7 @@ namespace WebCore { // properties. if (info.Holder()->HasRealNamedCallbackProperty(name)) return notHandledByInterceptor(); - Collection* collection = V8Proxy::DOMWrapperToNode<Collection>(info.Holder()); + Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); String propertyName = toWebCoreString(name); void* implementation = collection->namedItem(propertyName); return getV8Object(implementation, info.Data()); @@ -109,10 +109,10 @@ namespace WebCore { v8::Local<v8::Value> implementationType) { // FIXME: Assert that object must be a collection type. - ASSERT(V8Proxy::MaybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType wrapperType = V8Proxy::GetDOMWrapperType(object); + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(object); ASSERT(wrapperType != V8ClassIndex::NODE); - Collection* collection = V8Proxy::ToNativeObject<Collection>(wrapperType, object); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, object); return getV8Object<ItemType>(collection->item(index), implementationType); } @@ -125,9 +125,9 @@ namespace WebCore { // A template of index interceptor of HTMLSelectElement and HTMLFormElement. template<class Collection> static v8::Handle<v8::Value> nodeCollectionIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); - Collection* collection = V8Proxy::DOMWrapperToNode<Collection>(info.Holder()); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); + Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); void* implementation = collection->item(index); return getV8Object(implementation, info.Data()); } @@ -135,9 +135,9 @@ namespace WebCore { // Get an array containing the names of indexed properties of HTMLSelectElement and HTMLFormElement. template<class Collection> static v8::Handle<v8::Array> nodeCollectionIndexedPropertyEnumerator(const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); - Collection* collection = V8Proxy::DOMWrapperToNode<Collection>(info.Holder()); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); + Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); int length = collection->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (int i = 0; i < length; ++i) { @@ -151,9 +151,9 @@ namespace WebCore { // Get an array containing the names of indexed properties in a collection. template<class Collection> static v8::Handle<v8::Array> collectionIndexedPropertyEnumerator(const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType wrapperType = V8Proxy::GetDOMWrapperType(info.Holder()); - Collection* collection = V8Proxy::ToNativeObject<Collection>(wrapperType, info.Holder()); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); int length = collection->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (int i = 0; i < length; ++i) { @@ -169,9 +169,9 @@ namespace WebCore { template<class Collection> static v8::Handle<v8::Value> collectionStringOrNullIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { // FIXME: assert that object must be a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType wrapperType = V8Proxy::GetDOMWrapperType(info.Holder()); - Collection* collection = V8Proxy::ToNativeObject<Collection>(wrapperType, info.Holder()); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); String result = collection->item(index); return v8StringOrNull(result); } diff --git a/WebCore/bindings/v8/V8ConsoleMessage.cpp b/WebCore/bindings/v8/V8ConsoleMessage.cpp new file mode 100644 index 0000000..d9fe069 --- /dev/null +++ b/WebCore/bindings/v8/V8ConsoleMessage.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8ConsoleMessage.h" + +#include "Console.h" +#include "DOMWindow.h" +#include "Frame.h" +#include "OwnPtr.h" +#include "Page.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +namespace WebCore { + +Vector<V8ConsoleMessage>* V8ConsoleMessage::m_delayedMessages = 0; + +V8ConsoleMessage::V8ConsoleMessage(const String& string, const String& sourceID, unsigned lineNumber) + : m_string(string) + , m_sourceID(sourceID) + , m_lineNumber(lineNumber) +{ +} + +void V8ConsoleMessage::dispatchNow(Page* page) +{ + ASSERT(page); + + // Process any delayed messages to make sure that messages + // appear in the right order in the console. + processDelayed(); + + Console* console = page->mainFrame()->domWindow()->console(); + console->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID); +} + +void V8ConsoleMessage::dispatchLater() +{ + if (!m_delayedMessages) { + // Allocate a vector for the delayed messages. Will be + // deallocated when the delayed messages are processed + // in processDelayed(). + m_delayedMessages = new Vector<V8ConsoleMessage>(); + } + + m_delayedMessages->append(*this); +} + +void V8ConsoleMessage::processDelayed() +{ + if (!m_delayedMessages) + return; + + // Take ownership of the delayed vector to avoid re-entrancy issues. + OwnPtr<Vector<V8ConsoleMessage> > delayedMessages(m_delayedMessages); + m_delayedMessages = 0; + + // If we have a delayed vector it cannot be empty. + ASSERT(!delayedMessages->isEmpty()); + + // Add the delayed messages to the page of the active + // context. If that for some bizarre reason does not + // exist, we clear the list of delayed messages to avoid + // posting messages. We still deallocate the vector. + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + if (!frame) + return; + Page* page = frame->page(); + if (!page) + return; + + // Iterate through all the delayed messages and add them + // to the console. + const int size = delayedMessages->size(); + for (int i = 0; i < size; ++i) + delayedMessages->at(i).dispatchNow(page); +} + +void V8ConsoleMessage::handler(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) +{ + // Use the frame where JavaScript is called from. + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + if (!frame) + return; + Page* page = frame->page(); + if (!page) + return; + + v8::Handle<v8::String> errorMessageString = message->Get(); + ASSERT(!errorMessageString.IsEmpty()); + String errorMessage = toWebCoreString(errorMessageString); + + v8::Handle<v8::Value> resourceName = message->GetScriptResourceName(); + bool useURL = resourceName.IsEmpty() || !resourceName->IsString(); + String resourceNameString = useURL ? frame->document()->url() : toWebCoreString(resourceName); + V8ConsoleMessage consoleMessage(errorMessage, resourceNameString, message->GetLineNumber()); + consoleMessage.dispatchNow(page); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8ConsoleMessage.h b/WebCore/bindings/v8/V8ConsoleMessage.h new file mode 100644 index 0000000..a8f75ee --- /dev/null +++ b/WebCore/bindings/v8/V8ConsoleMessage.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8ConsoleMessage_h +#define V8ConsoleMessage_h + +#include "PlatformString.h" +#include <v8.h> +#include <wtf/Vector.h> + +namespace WebCore { + + class Page; + + // V8ConsoleMessage encapsulates everything needed to + // log messages originating from JavaScript to the console. + class V8ConsoleMessage { + public: + V8ConsoleMessage(const String& string, const String& sourceID, unsigned lineNumber); + + // Add a message to the console. May end up calling JavaScript code + // indirectly through the inspector so only call this function when + // it is safe to do allocations. + void dispatchNow(Page*); + + // Add a message to the console but delay the reporting until it + // is safe to do so: Either when we leave JavaScript execution or + // when adding other console messages. The primary purpose of this + // method is to avoid calling into V8 to handle console messages + // when the VM is in a state that does not support GCs or allocations. + // Delayed messages are always reported in the page corresponding + // to the active context. + void dispatchLater(); + + // Process any delayed messages. May end up calling JavaScript code + // indirectly through the inspector so only call this function when + // it is safe to do allocations. + static void processDelayed(); + + // Convenience class for ensuring that delayed messages in the + // ConsoleMessageManager are processed quickly. + class Scope { + public: + Scope() { V8ConsoleMessage::processDelayed(); } + ~Scope() { V8ConsoleMessage::processDelayed(); } + }; + + // Callback from V8. + static void handler(v8::Handle<v8::Message>, v8::Handle<v8::Value> data); + + private: + const String m_string; + const String m_sourceID; + const unsigned m_lineNumber; + + // All delayed messages are stored in this vector. If the vector + // is 0, there are no delayed messages. + static Vector<V8ConsoleMessage>* m_delayedMessages; + }; + +} // namespace WebCore + +#endif // V8ConsoleMessage_h diff --git a/WebCore/bindings/v8/V8DOMMap.cpp b/WebCore/bindings/v8/V8DOMMap.cpp index 4645c02..2d6639f 100644 --- a/WebCore/bindings/v8/V8DOMMap.cpp +++ b/WebCore/bindings/v8/V8DOMMap.cpp @@ -31,19 +31,14 @@ #include "config.h" #include "V8DOMMap.h" +#include "DOMData.h" +#include "DOMDataStore.h" #include "DOMObjectsInclude.h" - -#include <v8.h> -#include <wtf/HashMap.h> -#include <wtf/MainThread.h> -#include <wtf/Noncopyable.h> -#include <wtf/StdLibExtras.h> -#include <wtf/Threading.h> -#include <wtf/ThreadSpecific.h> -#include <wtf/Vector.h> +#include "ScopedDOMDataStore.h" namespace WebCore { +#ifdef MANUAL_MERGE_REQUIRED // DOM binding algorithm: // // There are two kinds of DOM objects: @@ -289,291 +284,174 @@ template<typename T> static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objectType, T*); ThreadSpecificDOMData& getThreadSpecificDOMData() +#else // MANUAL_MERGE_REQUIRED +DOMDataStoreHandle::DOMDataStoreHandle() + : m_store(new ScopedDOMDataStore(DOMData::getCurrent())) +#endif // MANUAL_MERGE_REQUIRED { - if (WTF::isMainThread()) { - DEFINE_STATIC_LOCAL(MainThreadSpecificDOMData, mainThreadSpecificDOMData, ()); - return mainThreadSpecificDOMData; - } - return *threadSpecificDOMData; } -template <class KeyType> -void ThreadSpecificDOMData::InternalDOMWrapperMap<KeyType>::forget(KeyType* object) +DOMDataStoreHandle::~DOMDataStoreHandle() { - DOMWrapperMap<KeyType>::forget(object); - - ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecificDOMData().delayedObjectMap(); - delayedObjectMap.take(object); } DOMWrapperMap<Node>& getDOMNodeMap() { - return getThreadSpecificDOMData().domNodeMap(); + // Nodes only exist on the main thread. + return DOMData::getCurrentMainThread()->getStore().domNodeMap(); } DOMWrapperMap<void>& getDOMObjectMap() { - return getThreadSpecificDOMData().domObjectMap(); + return DOMData::getCurrent()->getStore().domObjectMap(); } DOMWrapperMap<void>& getActiveDOMObjectMap() { - return getThreadSpecificDOMData().activeDomObjectMap(); + return DOMData::getCurrent()->getStore().activeDomObjectMap(); } #if ENABLE(SVG) -DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() -{ - return getThreadSpecificDOMData().domSvgElementInstanceMap(); -} -static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() { - SVGElementInstance* instance = static_cast<SVGElementInstance*>(domObject); - - ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>&>(getDOMSVGElementInstanceMap()); - if (map.contains(instance)) { - instance->deref(); - map.forgetOnly(instance); - } else - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGElementInstanceMap, V8ClassIndex::SVGELEMENTINSTANCE, instance); + return DOMData::getCurrent()->getStore().domSvgElementInstanceMap(); } // Map of SVG objects with contexts to V8 objects DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() { - return getThreadSpecificDOMData().domSvgObjectWithContextMap(); + return DOMData::getCurrent()->getStore().domSvgObjectWithContextMap(); } -static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject) -{ - v8::HandleScope scope; - ASSERT(v8Object->IsObject()); - - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); - - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMSVGObjectWithContextMap()); - if (map.contains(domObject)) { - // The forget function removes object from the map and disposes the wrapper. - map.forgetOnly(domObject); - - switch (type) { -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - SVG_OBJECT_TYPES(MakeCase) -#undef MakeCase -#define MakeCase(type, name) \ - case V8ClassIndex::type: \ - static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break; - SVG_POD_NATIVE_TYPES(MakeCase) -#undef MakeCase - default: - ASSERT_NOT_REACHED(); - break; - } - } else - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGObjectWithContextMap, type, domObject); -} #endif // ENABLE(SVG) -// Called when the dead object is not in GC thread's map. Go through all thread maps to find the one containing it. -// Then clear the JS reference and push the DOM object into the delayed queue for it to be deref-ed at later time from the owning thread. -// * This is called when the GC thread is not the owning thread. -// * This can be called on any thread that has GC running. -// * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency. -template<typename T> -static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objectType, T* object) +static void removeAllDOMObjectsInCurrentThreadHelper() { - WTF::MutexLocker locker(domDataListMutex()); - DOMDataList& list = domDataList(); - for (size_t i = 0; i < list.size(); ++i) { - ThreadSpecificDOMData* threadData = list[i]; + v8::HandleScope scope; - ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(mapType)); - if (domMap->contains(object)) { - // Clear the JS reference. - domMap->forgetOnly(object); + // Deref all objects in the delayed queue. + DOMData::getCurrent()->derefDelayedObjects(); - // Push into the delayed queue. - threadData->delayedObjectMap().set(object, objectType); + // The DOM objects with the following types only exist on the main thread. + if (WTF::isMainThread()) { + // Remove all DOM nodes. + DOMData::removeObjectsFromWrapperMap<Node>(getDOMNodeMap()); - // Post a task to the owning thread in order to process the delayed queue. - // FIXME: For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker. - if (!threadData->delayedProcessingScheduled()) { - threadData->setDelayedProcessingScheduled(true); - if (threadData->isMainThread()) - WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0); - } +#if ENABLE(SVG) + // Remove all SVG element instances in the wrapper map. + DOMData::removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap()); - break; - } + // Remove all SVG objects with context in the wrapper map. + DOMData::removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); +#endif } -} - -// Called when the object is near death (not reachable from JS roots). -// It is time to remove the entry from the table and dispose the handle. -static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) -{ - v8::HandleScope scope; - ASSERT(v8Object->IsObject()); - - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMObjectMap()); - if (map.contains(domObject)) { - // The forget function removes object from the map and disposes the wrapper. - map.forgetOnly(domObject); + // Remove all DOM objects in the wrapper map. + DOMData::removeObjectsFromWrapperMap<void>(getDOMObjectMap()); - switch (type) { -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - DOM_OBJECT_TYPES(MakeCase) -#undef MakeCase - default: - ASSERT_NOT_REACHED(); - break; - } - } else - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMObjectMap, type, domObject); + // Remove all active DOM objects in the wrapper map. + DOMData::removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); } -void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +void removeAllDOMObjectsInCurrentThread() { - v8::HandleScope scope; - ASSERT(v8Object->IsObject()); - - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); - - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getActiveDOMObjectMap()); - if (map.contains(domObject)) { - // The forget function removes object from the map and disposes the wrapper. - map.forgetOnly(domObject); - - switch (type) { -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - ACTIVE_DOM_OBJECT_TYPES(MakeCase) -#undef MakeCase - default: - ASSERT_NOT_REACHED(); - break; - } + // Use the locker only if it has already been invoked before, as by worker thread. + if (v8::Locker::IsActive()) { + v8::Locker locker; + removeAllDOMObjectsInCurrentThreadHelper(); } else - handleWeakObjectInOwningThread(ThreadSpecificDOMData::ActiveDOMObjectMap, type, domObject); + removeAllDOMObjectsInCurrentThreadHelper(); } -static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject) + +void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor* visitor) { - Node* node = static_cast<Node*>(domObject); + v8::HandleScope scope; - ThreadSpecificDOMData::InternalDOMWrapperMap<Node>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<Node>&>(getDOMNodeMap()); - if (map.contains(node)) { - map.forgetOnly(node); - node->deref(); - } else - handleWeakObjectInOwningThread<Node>(ThreadSpecificDOMData::DOMNodeMap, V8ClassIndex::NODE, node); + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; + + HashMap<Node*, v8::Object*>& map = store->domNodeMap().impl(); + for (HashMap<Node*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + } } -static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject) +void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) { - switch (type) { - case V8ClassIndex::NODE: - static_cast<Node*>(domObject)->deref(); - break; - -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active. -#undef MakeCase + v8::HandleScope scope; -#if ENABLE(SVG) -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - SVG_OBJECT_TYPES(MakeCase) // This also includes SVGElementInstance. -#undef MakeCase - -#define MakeCase(type, name) \ - case V8ClassIndex::type: \ - static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break; - SVG_POD_NATIVE_TYPES(MakeCase) -#undef MakeCase -#endif + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; - default: - ASSERT_NOT_REACHED(); - break; + HashMap<void*, v8::Object*> & map = store->domObjectMap().impl(); + for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); } } -static void derefDelayedObjects() +void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) { - WTF::MutexLocker locker(domDataListMutex()); + v8::HandleScope scope; - getThreadSpecificDOMData().setDelayedProcessingScheduled(false); + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; - ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecificDOMData().delayedObjectMap(); - for (ThreadSpecificDOMData::DelayedObjectMap::iterator iter(delayedObjectMap.begin()); iter != delayedObjectMap.end(); ++iter) { - derefObject(iter->second, iter->first); + HashMap<void*, v8::Object*>& map = store->activeDomObjectMap().impl(); + for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); } - delayedObjectMap.clear(); } -static void derefDelayedObjectsInCurrentThread(void*) -{ - derefDelayedObjects(); -} +#if ENABLE(SVG) -template<typename T> -static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) +void visitDOMSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor* visitor) { - for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) { - T* domObject = static_cast<T*>(iter->first); - v8::Persistent<v8::Object> v8Object(iter->second); - - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); + v8::HandleScope scope; - // Deref the DOM object. - derefObject(type, domObject); + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; - // Clear the JS wrapper. - v8Object.Dispose(); + HashMap<SVGElementInstance*, v8::Object*> & map = store->domSvgElementInstanceMap().impl(); + for (HashMap<SVGElementInstance*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); } - domMap.impl().clear(); } -static void removeAllDOMObjectsInCurrentThreadHelper() +void visitSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) { v8::HandleScope scope; - // Deref all objects in the delayed queue. - derefDelayedObjects(); - - // Remove all DOM nodes. - removeObjectsFromWrapperMap<Node>(getDOMNodeMap()); - - // Remove all DOM objects in the wrapper map. - removeObjectsFromWrapperMap<void>(getDOMObjectMap()); - - // Remove all active DOM objects in the wrapper map. - removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); - -#if ENABLE(SVG) - // Remove all SVG element instances in the wrapper map. - removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap()); + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; - // Remove all SVG objects with context in the wrapper map. - removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); -#endif + HashMap<void*, v8::Object*>& map = store->domSvgObjectWithContextMap().impl(); + for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + } } -void removeAllDOMObjectsInCurrentThread() -{ - // Use the locker only if it has already been invoked before, as by worker thread. - if (v8::Locker::IsActive()) { - v8::Locker locker; - removeAllDOMObjectsInCurrentThreadHelper(); - } else - removeAllDOMObjectsInCurrentThreadHelper(); -} +#endif } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMMap.h b/WebCore/bindings/v8/V8DOMMap.h index 47fa765..eac39d2 100644 --- a/WebCore/bindings/v8/V8DOMMap.h +++ b/WebCore/bindings/v8/V8DOMMap.h @@ -32,6 +32,7 @@ #define V8DOMMap_h #include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> #include <v8.h> namespace WebCore { @@ -48,10 +49,18 @@ namespace WebCore { WeakReferenceMap(v8::WeakReferenceCallback callback) : m_weakReferenceCallback(callback) { } virtual ~WeakReferenceMap() { +#ifdef MANUAL_MERGE_REQUIRED #ifndef NDEBUG +#else // MANUAL_MERGE_REQUIRED + #ifndef NDEBUG +#endif // MANUAL_MERGE_REQUIRED if (m_map.size() > 0) fprintf(stderr, "Leak %d JS wrappers.\n", m_map.size()); +#ifdef MANUAL_MERGE_REQUIRED #endif +#else // MANUAL_MERGE_REQUIRED + #endif +#endif // MANUAL_MERGE_REQUIRED } // Get the JS wrapper object of an object. @@ -89,23 +98,42 @@ namespace WebCore { v8::WeakReferenceCallback m_weakReferenceCallback; }; - template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> { public: DOMWrapperMap(v8::WeakReferenceCallback callback) : WeakReferenceMap<KeyType, v8::Object>(callback) { } + + class Visitor { + public: + virtual void visitDOMWrapper(KeyType* key, v8::Persistent<v8::Object> object) = 0; + }; }; - // Callback when JS wrapper of active DOM object is dead. - void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); + // An opaque class that represents a set of DOM wrappers. + class DOMDataStore; + + // A utility class to manage the lifetime of set of DOM wrappers. + class DOMDataStoreHandle { + public: + DOMDataStoreHandle(); + ~DOMDataStoreHandle(); + + DOMDataStore* getStore() const { return m_store.get(); } + + private: + OwnPtr<DOMDataStore> m_store; + }; // A map from DOM node to its JS wrapper. DOMWrapperMap<Node>& getDOMNodeMap(); + void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor*); // A map from a DOM object (non-node) to its JS wrapper. This map does not contain the DOM objects which can have pending activity (active dom objects). DOMWrapperMap<void>& getDOMObjectMap(); + void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); // A map from a DOM object to its JS wrapper for DOM objects which can have pending activity. DOMWrapperMap<void>& getActiveDOMObjectMap(); + void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); // This should be called to remove all DOM objects associated with the current thread when it is tearing down. void removeAllDOMObjectsInCurrentThread(); @@ -113,9 +141,11 @@ namespace WebCore { #if ENABLE(SVG) // A map for SVGElementInstances to its JS wrapper. DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap(); + void visitSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor*); // Map of SVG objects with contexts to V8 objects. DOMWrapperMap<void>& getDOMSVGObjectWithContextMap(); + void visitDOMSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); #endif } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp new file mode 100644 index 0000000..33d1147 --- /dev/null +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -0,0 +1,1465 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8DOMWrapper.h" + +#include "ChromiumBridge.h" +#include "CSSMutableStyleDeclaration.h" +#include "DOMObjectsInclude.h" +#include "DocumentLoader.h" +#include "FrameLoaderClient.h" +#include "ScriptController.h" +#include "V8Binding.h" +#include "V8Collection.h" +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8DOMWindow.h" +#include "V8Index.h" +#include "V8IsolatedWorld.h" +#include "WorkerContextExecutionProxy.h" + +#include <algorithm> +#include <utility> +#include <v8.h> +#include <v8-debug.h> +#include <wtf/Assertions.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> + +namespace WebCore { + +typedef HashMap<Node*, v8::Object*> DOMNodeMap; +typedef HashMap<void*, v8::Object*> DOMObjectMap; + +// Get the string 'toString'. +static v8::Persistent<v8::String> GetToStringName() +{ + DEFINE_STATIC_LOCAL(v8::Persistent<v8::String>, value, ()); + if (value.IsEmpty()) + value = v8::Persistent<v8::String>::New(v8::String::New("toString")); + return value; +} + +static v8::Handle<v8::Value> ConstructorToString(const v8::Arguments& args) +{ + // The DOM constructors' toString functions grab the current toString + // for Functions by taking the toString function of itself and then + // calling it with the constructor as its receiver. This means that + // changes to the Function prototype chain or toString function are + // reflected when printing DOM constructors. The only wart is that + // changes to a DOM constructor's toString's toString will cause the + // toString of the DOM constructor itself to change. This is extremely + // obscure and unlikely to be a problem. + v8::Handle<v8::Value> value = args.Callee()->Get(GetToStringName()); + if (!value->IsFunction()) + return v8::String::New(""); + return v8::Handle<v8::Function>::Cast(value)->Call(args.This(), 0, 0); +} + +#if ENABLE(SVG) +v8::Handle<v8::Value> V8DOMWrapper::convertSVGElementInstanceToV8Object(SVGElementInstance* instance) +{ + if (!instance) + return v8::Null(); + + v8::Handle<v8::Object> existingInstance = getDOMSVGElementInstanceMap().get(instance); + if (!existingInstance.IsEmpty()) + return existingInstance; + + instance->ref(); + + // Instantiate the V8 object and remember it + v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::SVGELEMENTINSTANCE, V8ClassIndex::SVGELEMENTINSTANCE, instance); + if (!result.IsEmpty()) { + // Only update the DOM SVG element map if the result is non-empty. + getDOMSVGElementInstanceMap().set(instance, v8::Persistent<v8::Object>::New(result)); + } + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType type, void* object) +{ + if (!object) + return v8::Null(); + + v8::Persistent<v8::Object> result = getDOMSVGObjectWithContextMap().get(object); + if (!result.IsEmpty()) + return result; + + // Special case: SVGPathSegs need to be downcast to their real type + if (type == V8ClassIndex::SVGPATHSEG) + type = V8Custom::DowncastSVGPathSeg(object); + + v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, object); + if (!v8Object.IsEmpty()) { + result = v8::Persistent<v8::Object>::New(v8Object); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(object)->ref(); break; + SVG_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: \ + static_cast<V8SVGPODTypeWrapper<NAME>*>(object)->ref(); break; + SVG_POD_NATIVE_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT_NOT_REACHED(); + } + getDOMSVGObjectWithContextMap().set(object, result); + } + + return result; +} + +#endif + +bool V8DOMWrapper::domObjectHasJSWrapper(void* object) +{ + return getDOMObjectMap().contains(object) || getActiveDOMObjectMap().contains(object); +} + +// The caller must have increased obj's ref count. +void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); +#ifndef NDEBUG + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + ASSERT_NOT_REACHED(); +#undef MAKE_CASE + default: + break; + } +#endif + getDOMObjectMap().set(object, wrapper); +} + +// The caller must have increased obj's ref count. +void V8DOMWrapper::setJSWrapperForActiveDOMObject(void* object, v8::Persistent<v8::Object> wrapper) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); +#ifndef NDEBUG + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break; + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: + ASSERT_NOT_REACHED(); +#undef MAKE_CASE + } +#endif + getActiveDOMObjectMap().set(object, wrapper); +} + +// The caller must have increased node's ref count. +void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); + getDOMNodeMap().set(node, wrapper); +} + +v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8WrapperType type) +{ + v8::Persistent<v8::FunctionTemplate>* cacheCell = V8ClassIndex::GetCache(type); + if (!cacheCell->IsEmpty()) + return *cacheCell; + + // Not in the cache. + FunctionTemplateFactory factory = V8ClassIndex::GetFactory(type); + v8::Persistent<v8::FunctionTemplate> descriptor = factory(); + // DOM constructors are functions and should print themselves as such. + // However, we will later replace their prototypes with Object + // prototypes so we need to explicitly override toString on the + // instance itself. If we later make DOM constructors full objects + // we can give them class names instead and Object.prototype.toString + // will work so we can remove this code. + DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ()); + if (toStringTemplate.IsEmpty()) + toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(ConstructorToString)); + descriptor->Set(GetToStringName(), toStringTemplate); + switch (type) { + case V8ClassIndex::CSSSTYLEDECLARATION: + // The named property handler for style declarations has a + // setter. Therefore, the interceptor has to be on the object + // itself and not on the prototype object. + descriptor->InstanceTemplate()->SetNamedPropertyHandler( USE_NAMED_PROPERTY_GETTER(CSSStyleDeclaration), USE_NAMED_PROPERTY_SETTER(CSSStyleDeclaration)); + setCollectionStringOrNullIndexedGetter<CSSStyleDeclaration>(descriptor); + break; + case V8ClassIndex::CSSRULELIST: + setCollectionIndexedGetter<CSSRuleList, CSSRule>(descriptor, V8ClassIndex::CSSRULE); + break; + case V8ClassIndex::CSSVALUELIST: + setCollectionIndexedGetter<CSSValueList, CSSValue>(descriptor, V8ClassIndex::CSSVALUE); + break; + case V8ClassIndex::CSSVARIABLESDECLARATION: + setCollectionStringOrNullIndexedGetter<CSSVariablesDeclaration>(descriptor); + break; + case V8ClassIndex::WEBKITCSSTRANSFORMVALUE: + setCollectionIndexedGetter<WebKitCSSTransformValue, CSSValue>(descriptor, V8ClassIndex::CSSVALUE); + break; + case V8ClassIndex::HTMLALLCOLLECTION: + descriptor->InstanceTemplate()->MarkAsUndetectable(); // fall through + case V8ClassIndex::HTMLCOLLECTION: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLCollection)); + descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLCollectionCallAsFunction)); + setCollectionIndexedGetter<HTMLCollection, Node>(descriptor, V8ClassIndex::NODE); + break; + case V8ClassIndex::HTMLOPTIONSCOLLECTION: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLCollection)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLOptionsCollection), USE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection)); + descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLCollectionCallAsFunction)); + break; + case V8ClassIndex::HTMLSELECTELEMENT: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(nodeCollectionIndexedPropertyGetter<HTMLSelectElement>, USE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection), + 0, 0, nodeCollectionIndexedPropertyEnumerator<HTMLSelectElement>, v8::Integer::New(V8ClassIndex::NODE)); + break; + case V8ClassIndex::HTMLDOCUMENT: { + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLDocument), 0, 0, USE_NAMED_PROPERTY_DELETER(HTMLDocument)); + + // We add an extra internal field to all Document wrappers for + // storing a per document DOMImplementation wrapper. + // + // Additionally, we add two extra internal fields for + // HTMLDocuments to implement temporary shadowing of + // document.all. One field holds an object that is used as a + // marker. The other field holds the marker object if + // document.all is not shadowed and some other value if + // document.all is shadowed. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kNodeMinimumInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kHTMLDocumentInternalFieldCount); + break; + } +#if ENABLE(SVG) + case V8ClassIndex::SVGDOCUMENT: // fall through +#endif + case V8ClassIndex::DOCUMENT: { + // We add an extra internal field to all Document wrappers for + // storing a per document DOMImplementation wrapper. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kNodeMinimumInternalFieldCount); + instanceTemplate->SetInternalFieldCount( V8Custom::kDocumentMinimumInternalFieldCount); + break; + } + case V8ClassIndex::HTMLAPPLETELEMENT: // fall through + case V8ClassIndex::HTMLEMBEDELEMENT: // fall through + case V8ClassIndex::HTMLOBJECTELEMENT: + // HTMLAppletElement, HTMLEmbedElement and HTMLObjectElement are + // inherited from HTMLPlugInElement, and they share the same property + // handling code. + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLPlugInElement), USE_NAMED_PROPERTY_SETTER(HTMLPlugInElement)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLPlugInElement), USE_INDEXED_PROPERTY_SETTER(HTMLPlugInElement)); + descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLPlugInElement)); + break; + case V8ClassIndex::HTMLFRAMESETELEMENT: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFrameSetElement)); + break; + case V8ClassIndex::HTMLFORMELEMENT: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFormElement)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLFormElement), 0, 0, 0, nodeCollectionIndexedPropertyEnumerator<HTMLFormElement>, v8::Integer::New(V8ClassIndex::NODE)); + break; + case V8ClassIndex::STYLESHEET: // fall through + case V8ClassIndex::CSSSTYLESHEET: { + // We add an extra internal field to hold a reference to + // the owner node. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kStyleSheetInternalFieldCount); + break; + } + case V8ClassIndex::MEDIALIST: + setCollectionStringOrNullIndexedGetter<MediaList>(descriptor); + break; + case V8ClassIndex::MIMETYPEARRAY: + setCollectionIndexedAndNamedGetters<MimeTypeArray, MimeType>(descriptor, V8ClassIndex::MIMETYPE); + break; + case V8ClassIndex::NAMEDNODEMAP: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NamedNodeMap)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(NamedNodeMap), 0, 0, 0, collectionIndexedPropertyEnumerator<NamedNodeMap>, v8::Integer::New(V8ClassIndex::NODE)); + break; +#if ENABLE(DOM_STORAGE) + case V8ClassIndex::STORAGE: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(Storage), USE_NAMED_PROPERTY_SETTER(Storage), 0, USE_NAMED_PROPERTY_DELETER(Storage), V8Custom::v8StorageNamedPropertyEnumerator); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(Storage), USE_INDEXED_PROPERTY_SETTER(Storage), 0, USE_INDEXED_PROPERTY_DELETER(Storage)); + break; +#endif + case V8ClassIndex::NODELIST: + setCollectionIndexedGetter<NodeList, Node>(descriptor, V8ClassIndex::NODE); + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NodeList)); + break; + case V8ClassIndex::PLUGIN: + setCollectionIndexedAndNamedGetters<Plugin, MimeType>(descriptor, V8ClassIndex::MIMETYPE); + break; + case V8ClassIndex::PLUGINARRAY: + setCollectionIndexedAndNamedGetters<PluginArray, Plugin>(descriptor, V8ClassIndex::PLUGIN); + break; + case V8ClassIndex::STYLESHEETLIST: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(StyleSheetList)); + setCollectionIndexedGetter<StyleSheetList, StyleSheet>(descriptor, V8ClassIndex::STYLESHEET); + break; + case V8ClassIndex::DOMWINDOW: { + v8::Local<v8::Signature> defaultSignature = v8::Signature::New(descriptor); + + descriptor->PrototypeTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DOMWindow)); + descriptor->PrototypeTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DOMWindow)); + + descriptor->SetHiddenPrototype(true); + + // Reserve spaces for references to location, history and + // navigator objects. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount); + + // Set access check callbacks, but turned off initially. + // When a context is detached from a frame, turn on the access check. + // Turning on checks also invalidates inline caches of the object. + instanceTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false); + break; + } + case V8ClassIndex::LOCATION: { + // For security reasons, these functions are on the instance + // instead of on the prototype object to insure that they cannot + // be overwritten. + v8::Local<v8::ObjectTemplate> instance = descriptor->InstanceTemplate(); + instance->SetAccessor(v8::String::New("reload"), V8Custom::v8LocationReloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + instance->SetAccessor(v8::String::New("replace"), V8Custom::v8LocationReplaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + instance->SetAccessor(v8::String::New("assign"), V8Custom::v8LocationAssignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + break; + } + case V8ClassIndex::HISTORY: + break; + + case V8ClassIndex::MESSAGECHANNEL: { + // Reserve two more internal fields for referencing the port1 + // and port2 wrappers. This ensures that the port wrappers are + // kept alive when the channel wrapper is. + descriptor->SetCallHandler(USE_CALLBACK(MessageChannelConstructor)); + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kMessageChannelInternalFieldCount); + break; + } + + case V8ClassIndex::MESSAGEPORT: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kMessagePortInternalFieldCount); + break; + } + +#if ENABLE(WORKERS) + case V8ClassIndex::ABSTRACTWORKER: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kAbstractWorkerInternalFieldCount); + break; + } + + case V8ClassIndex::DEDICATEDWORKERCONTEXT: { + // Reserve internal fields for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kDedicatedWorkerContextInternalFieldCount); + break; + } + + case V8ClassIndex::WORKER: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kWorkerInternalFieldCount); + descriptor->SetCallHandler(USE_CALLBACK(WorkerConstructor)); + break; + } + + case V8ClassIndex::WORKERCONTEXT: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kWorkerContextMinimumInternalFieldCount); + break; + } + +#endif // WORKERS + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + case V8ClassIndex::DOMAPPLICATIONCACHE: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kDOMApplicationCacheFieldCount); + break; + } +#endif + + // The following objects are created from JavaScript. + case V8ClassIndex::DOMPARSER: + descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor)); + break; +#if ENABLE(VIDEO) + case V8ClassIndex::HTMLAUDIOELEMENT: + descriptor->SetCallHandler(USE_CALLBACK(HTMLAudioElementConstructor)); + break; +#endif + case V8ClassIndex::HTMLIMAGEELEMENT: + descriptor->SetCallHandler(USE_CALLBACK(HTMLImageElementConstructor)); + break; + case V8ClassIndex::HTMLOPTIONELEMENT: + descriptor->SetCallHandler(USE_CALLBACK(HTMLOptionElementConstructor)); + break; + case V8ClassIndex::WEBKITCSSMATRIX: + descriptor->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor)); + break; + case V8ClassIndex::WEBKITPOINT: + descriptor->SetCallHandler(USE_CALLBACK(WebKitPointConstructor)); + break; + case V8ClassIndex::XMLSERIALIZER: + descriptor->SetCallHandler(USE_CALLBACK(XMLSerializerConstructor)); + break; + case V8ClassIndex::XMLHTTPREQUEST: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount); + descriptor->SetCallHandler(USE_CALLBACK(XMLHttpRequestConstructor)); + break; + } + case V8ClassIndex::XMLHTTPREQUESTUPLOAD: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount); + break; + } + case V8ClassIndex::XPATHEVALUATOR: + descriptor->SetCallHandler(USE_CALLBACK(XPathEvaluatorConstructor)); + break; + case V8ClassIndex::XSLTPROCESSOR: + descriptor->SetCallHandler(USE_CALLBACK(XSLTProcessorConstructor)); + break; + case V8ClassIndex::CLIENTRECTLIST: + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(ClientRectList)); + break; +#if ENABLE(DATAGRID) + case V8ClassIndex::DATAGRIDCOLUMNLIST: + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DataGridColumnList)); + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DataGridColumnList)); + break; +#endif + default: + break; + } + + *cacheCell = descriptor; + return descriptor; +} + +v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype) +{ + // A DOM constructor is a function instance created from a DOM constructor + // template. There is one instance per context. A DOM constructor is + // different from a normal function in two ways: + // 1) it cannot be called as constructor (aka, used to create a DOM object) + // 2) its __proto__ points to Object.prototype rather than + // Function.prototype. + // The reason for 2) is that, in Safari, a DOM constructor is a normal JS + // object, but not a function. Hotmail relies on the fact that, in Safari, + // HTMLElement.__proto__ == Object.prototype. + v8::Handle<v8::FunctionTemplate> functionTemplate = getTemplate(type); + // Getting the function might fail if we're running out of + // stack or memory. + v8::TryCatch tryCatch; + v8::Local<v8::Function> value = functionTemplate->GetFunction(); + if (value.IsEmpty()) + return v8::Local<v8::Function>(); + // Hotmail fix, see comments above. + if (!objectPrototype.IsEmpty()) + value->Set(v8::String::New("__proto__"), objectPrototype); + return value; +} + +v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context) +{ + // Enter the scope for this context to get the correct constructor. + v8::Context::Scope scope(context); + + return getConstructor(type, V8Proxy::getHiddenObjectPrototype(context)); +} + +v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window) +{ + Frame* frame = window->frame(); + if (!frame) + return v8::Local<v8::Function>(); + + v8::Handle<v8::Context> context = V8Proxy::context(frame); + if (context.IsEmpty()) + return v8::Local<v8::Function>(); + + return getConstructorForContext(type, context); +} + +v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*) +{ + WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + if (!proxy) + return v8::Local<v8::Function>(); + + v8::Handle<v8::Context> context = proxy->context(); + if (context.IsEmpty()) + return v8::Local<v8::Function>(); + + return getConstructorForContext(type, context); +} + +v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl) +{ + ASSERT(type != V8ClassIndex::EVENTLISTENER); + ASSERT(type != V8ClassIndex::EVENTTARGET); + ASSERT(type != V8ClassIndex::EVENT); + + // These objects can be constructed under WorkerContextExecutionProxy. They need special + // handling, since if we proceed below V8Proxy::retrieve() will get called and will crash. + if ((type == V8ClassIndex::DOMCOREEXCEPTION + || type == V8ClassIndex::RANGEEXCEPTION + || type == V8ClassIndex::EVENTEXCEPTION + || type == V8ClassIndex::XMLHTTPREQUESTEXCEPTION + || type == V8ClassIndex::MESSAGEPORT) + && WorkerContextExecutionProxy::retrieve()) { + return WorkerContextExecutionProxy::convertToV8Object(type, impl); + } + + bool isActiveDomObject = false; + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: + DOM_NODE_TYPES(MAKE_CASE) +#if ENABLE(SVG) + SVG_NODE_TYPES(MAKE_CASE) +#endif + return convertNodeToV8Object(static_cast<Node*>(impl)); + case V8ClassIndex::CSSVALUE: + return convertCSSValueToV8Object(static_cast<CSSValue*>(impl)); + case V8ClassIndex::CSSRULE: + return convertCSSRuleToV8Object(static_cast<CSSRule*>(impl)); + case V8ClassIndex::STYLESHEET: + return convertStyleSheetToV8Object(static_cast<StyleSheet*>(impl)); + case V8ClassIndex::DOMWINDOW: + return convertWindowToV8Object(static_cast<DOMWindow*>(impl)); +#if ENABLE(SVG) + SVG_NONNODE_TYPES(MAKE_CASE) + if (type == V8ClassIndex::SVGELEMENTINSTANCE) + return convertSVGElementInstanceToV8Object(static_cast<SVGElementInstance*>(impl)); + return convertSVGObjectWithContextToV8Object(type, impl); +#endif + + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + isActiveDomObject = true; + break; + default: + break; + } + +#undef MAKE_CASE + + if (!impl) + return v8::Null(); + + // Non DOM node + v8::Persistent<v8::Object> result = isActiveDomObject ? getActiveDOMObjectMap().get(impl) : getDOMObjectMap().get(impl); + if (result.IsEmpty()) { + v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, impl); + if (!v8Object.IsEmpty()) { + // Go through big switch statement, it has some duplications + // that were handled by code above (such as CSSVALUE, CSSRULE, etc). + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break; + DOM_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT_NOT_REACHED(); + } + result = v8::Persistent<v8::Object>::New(v8Object); + if (isActiveDomObject) + setJSWrapperForActiveDOMObject(impl, result); + else + setJSWrapperForDOMObject(impl, result); + + if (type == V8ClassIndex::CANVASPIXELARRAY) { + CanvasPixelArray* pixels = reinterpret_cast<CanvasPixelArray*>(impl); + result->SetIndexedPropertiesToPixelData(pixels->data()->data(), pixels->length()); + } + + // Special case for non-node objects associated with a + // DOMWindow. Both Safari and FF let the JS wrappers for these + // objects survive GC. To mimic their behavior, V8 creates + // hidden references from the DOMWindow to these wrapper + // objects. These references get cleared when the DOMWindow is + // reused by a new page. + switch (type) { + case V8ClassIndex::CONSOLE: + setHiddenWindowReference(static_cast<Console*>(impl)->frame(), V8Custom::kDOMWindowConsoleIndex, result); + break; + case V8ClassIndex::HISTORY: + setHiddenWindowReference(static_cast<History*>(impl)->frame(), V8Custom::kDOMWindowHistoryIndex, result); + break; + case V8ClassIndex::NAVIGATOR: + setHiddenWindowReference(static_cast<Navigator*>(impl)->frame(), V8Custom::kDOMWindowNavigatorIndex, result); + break; + case V8ClassIndex::SCREEN: + setHiddenWindowReference(static_cast<Screen*>(impl)->frame(), V8Custom::kDOMWindowScreenIndex, result); + break; + case V8ClassIndex::LOCATION: + setHiddenWindowReference(static_cast<Location*>(impl)->frame(), V8Custom::kDOMWindowLocationIndex, result); + break; + case V8ClassIndex::DOMSELECTION: + setHiddenWindowReference(static_cast<DOMSelection*>(impl)->frame(), V8Custom::kDOMWindowDOMSelectionIndex, result); + break; + case V8ClassIndex::BARINFO: { + BarInfo* barInfo = static_cast<BarInfo*>(impl); + Frame* frame = barInfo->frame(); + switch (barInfo->type()) { + case BarInfo::Locationbar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowLocationbarIndex, result); + break; + case BarInfo::Menubar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowMenubarIndex, result); + break; + case BarInfo::Personalbar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowPersonalbarIndex, result); + break; + case BarInfo::Scrollbars: + setHiddenWindowReference(frame, V8Custom::kDOMWindowScrollbarsIndex, result); + break; + case BarInfo::Statusbar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowStatusbarIndex, result); + break; + case BarInfo::Toolbar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowToolbarIndex, result); + break; + } + break; + } + default: + break; + } + } + } + return result; +} + +void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject) +{ + // Get DOMWindow + if (!frame) + return; // Object might be detached from window + v8::Handle<v8::Context> context = V8Proxy::context(frame); + if (context.IsEmpty()) + return; + + ASSERT(internalIndex < V8Custom::kDOMWindowInternalFieldCount); + + v8::Handle<v8::Object> global = context->Global(); + // Look for real DOM wrapper. + global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, global); + ASSERT(!global.IsEmpty()); + ASSERT(global->GetInternalField(internalIndex)->IsUndefined()); + global->SetInternalField(internalIndex, jsObject); +} + +V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + return V8ClassIndex::FromInt(type->Int32Value()); +} + +void* V8DOMWrapper::convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object) +{ + return isWrapperOfType(object, type) ? convertDOMWrapperToNative<void>(v8::Handle<v8::Object>::Cast(object)) : 0; +} + +PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter) +{ + // A NodeFilter is used when walking through a DOM tree or iterating tree + // nodes. + // FIXME: we may want to cache NodeFilterCondition and NodeFilter + // object, but it is minor. + // NodeFilter is passed to NodeIterator that has a ref counted pointer + // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition. + // In NodeFilterCondition, filter object is persisted in its constructor, + // and disposed in its destructor. + if (!filter->IsFunction()) + return 0; + + NodeFilterCondition* condition = new V8NodeFilterCondition(filter); + return NodeFilter::create(condition); +} + +v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl) +{ + // Make a special case for document.all + if (descriptorType == V8ClassIndex::HTMLCOLLECTION && static_cast<HTMLCollection*>(impl)->type() == DocAll) + descriptorType = V8ClassIndex::HTMLALLCOLLECTION; + + if (V8IsolatedWorld::getEntered()) { + // This effectively disables the wrapper cache for isolated worlds. + proxy = 0; + // FIXME: Do we need a wrapper cache for the isolated world? We should + // see if the performance gains are worth while. + } else if (!proxy) + proxy = V8Proxy::retrieve(); + + v8::Local<v8::Object> instance; + if (proxy) + instance = proxy->createWrapperFromCache(descriptorType); + else { + v8::Local<v8::Function> function = getTemplate(descriptorType)->GetFunction(); + instance = SafeAllocation::newInstance(function); + } + if (!instance.IsEmpty()) { + // Avoid setting the DOM wrapper for failed allocations. + setDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl); + } + return instance; +} + +void V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr) +{ + ASSERT(object->InternalFieldCount() >= 2); + object->SetPointerInInternalField(V8Custom::kDOMWrapperObjectIndex, cptr); + object->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type)); +} + +#ifndef NDEBUG +bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) +{ + if (value.IsEmpty() || !value->IsObject()) + return false; + + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + if (!object->InternalFieldCount()) + return false; + + ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount); + + v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + ASSERT(type->IsInt32()); + ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); + + v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); + ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); + + return true; +} +#endif + +bool V8DOMWrapper::isDOMEventWrapper(v8::Handle<v8::Value> value) +{ + // All kinds of events use EVENT as dom type in JS wrappers. + // See EventToV8Object + return isWrapperOfType(value, V8ClassIndex::EVENT); +} + +bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) +{ + if (value.IsEmpty() || !value->IsObject()) + return false; + + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + if (!object->InternalFieldCount()) + return false; + + ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount); + + v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); + ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); + + v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + ASSERT(type->IsInt32()); + ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); + + return V8ClassIndex::FromInt(type->Int32Value()) == classType; +} + +#if ENABLE(VIDEO) +#define FOR_EACH_VIDEO_TAG(macro) \ + macro(audio, AUDIO) \ + macro(source, SOURCE) \ + macro(video, VIDEO) +#else +#define FOR_EACH_VIDEO_TAG(macro) +#endif + +#if ENABLE(DATAGRID) +#define FOR_EACH_DATAGRID_TAG(macro) \ + macro(datagrid, DATAGRID) \ + macro(dcell, DATAGRIDCELL) \ + macro(dcol, DATAGRIDCOL) \ + macro(drow, DATAGRIDROW) +#else +#define FOR_EACH_DATAGRID_TAG(macro) +#endif + +#define FOR_EACH_TAG(macro) \ + FOR_EACH_DATAGRID_TAG(macro) \ + macro(a, ANCHOR) \ + macro(applet, APPLET) \ + macro(area, AREA) \ + macro(base, BASE) \ + macro(basefont, BASEFONT) \ + macro(blockquote, BLOCKQUOTE) \ + macro(body, BODY) \ + macro(br, BR) \ + macro(button, BUTTON) \ + macro(caption, TABLECAPTION) \ + macro(col, TABLECOL) \ + macro(colgroup, TABLECOL) \ + macro(del, MOD) \ + macro(canvas, CANVAS) \ + macro(dir, DIRECTORY) \ + macro(div, DIV) \ + macro(dl, DLIST) \ + macro(embed, EMBED) \ + macro(fieldset, FIELDSET) \ + macro(font, FONT) \ + macro(form, FORM) \ + macro(frame, FRAME) \ + macro(frameset, FRAMESET) \ + macro(h1, HEADING) \ + macro(h2, HEADING) \ + macro(h3, HEADING) \ + macro(h4, HEADING) \ + macro(h5, HEADING) \ + macro(h6, HEADING) \ + macro(head, HEAD) \ + macro(hr, HR) \ + macro(html, HTML) \ + macro(img, IMAGE) \ + macro(iframe, IFRAME) \ + macro(image, IMAGE) \ + macro(input, INPUT) \ + macro(ins, MOD) \ + macro(isindex, ISINDEX) \ + macro(keygen, SELECT) \ + macro(label, LABEL) \ + macro(legend, LEGEND) \ + macro(li, LI) \ + macro(link, LINK) \ + macro(listing, PRE) \ + macro(map, MAP) \ + macro(marquee, MARQUEE) \ + macro(menu, MENU) \ + macro(meta, META) \ + macro(object, OBJECT) \ + macro(ol, OLIST) \ + macro(optgroup, OPTGROUP) \ + macro(option, OPTION) \ + macro(p, PARAGRAPH) \ + macro(param, PARAM) \ + macro(pre, PRE) \ + macro(q, QUOTE) \ + macro(script, SCRIPT) \ + macro(select, SELECT) \ + macro(style, STYLE) \ + macro(table, TABLE) \ + macro(thead, TABLESECTION) \ + macro(tbody, TABLESECTION) \ + macro(tfoot, TABLESECTION) \ + macro(td, TABLECELL) \ + macro(th, TABLECELL) \ + macro(tr, TABLEROW) \ + macro(textarea, TEXTAREA) \ + macro(title, TITLE) \ + macro(ul, ULIST) \ + macro(xmp, PRE) + +V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element) +{ + typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap; + DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ()); + if (wrapperTypeMap.isEmpty()) { +#define ADD_TO_HASH_MAP(tag, name) \ + wrapperTypeMap.set(#tag, V8ClassIndex::HTML##name##ELEMENT); + FOR_EACH_TAG(ADD_TO_HASH_MAP) +#if ENABLE(VIDEO) + if (MediaPlayer::isAvailable()) { + FOR_EACH_VIDEO_TAG(ADD_TO_HASH_MAP) + } +#endif +#undef ADD_TO_HASH_MAP + } + + V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl()); + if (!type) + return V8ClassIndex::HTMLELEMENT; + return type; +} +#undef FOR_EACH_TAG + +#if ENABLE(SVG) + +#if ENABLE(SVG_ANIMATION) +#define FOR_EACH_ANIMATION_TAG(macro) \ + macro(animateColor, ANIMATECOLOR) \ + macro(animate, ANIMATE) \ + macro(animateTransform, ANIMATETRANSFORM) \ + macro(set, SET) +#else +#define FOR_EACH_ANIMATION_TAG(macro) +#endif + +#if ENABLE(SVG_FILTERS) +#define FOR_EACH_FILTERS_TAG(macro) \ + macro(feBlend, FEBLEND) \ + macro(feColorMatrix, FECOLORMATRIX) \ + macro(feComponentTransfer, FECOMPONENTTRANSFER) \ + macro(feComposite, FECOMPOSITE) \ + macro(feDiffuseLighting, FEDIFFUSELIGHTING) \ + macro(feDisplacementMap, FEDISPLACEMENTMAP) \ + macro(feDistantLight, FEDISTANTLIGHT) \ + macro(feFlood, FEFLOOD) \ + macro(feFuncA, FEFUNCA) \ + macro(feFuncB, FEFUNCB) \ + macro(feFuncG, FEFUNCG) \ + macro(feFuncR, FEFUNCR) \ + macro(feGaussianBlur, FEGAUSSIANBLUR) \ + macro(feImage, FEIMAGE) \ + macro(feMerge, FEMERGE) \ + macro(feMergeNode, FEMERGENODE) \ + macro(feOffset, FEOFFSET) \ + macro(fePointLight, FEPOINTLIGHT) \ + macro(feSpecularLighting, FESPECULARLIGHTING) \ + macro(feSpotLight, FESPOTLIGHT) \ + macro(feTile, FETILE) \ + macro(feTurbulence, FETURBULENCE) \ + macro(filter, FILTER) +#else +#define FOR_EACH_FILTERS_TAG(macro) +#endif + +#if ENABLE(SVG_FONTS) +#define FOR_EACH_FONTS_TAG(macro) \ + macro(definition-src, DEFINITIONSRC) \ + macro(font-face, FONTFACE) \ + macro(font-face-format, FONTFACEFORMAT) \ + macro(font-face-name, FONTFACENAME) \ + macro(font-face-src, FONTFACESRC) \ + macro(font-face-uri, FONTFACEURI) +#else +#define FOR_EACH_FONTS_TAG(marco) +#endif + +#if ENABLE(SVG_FOREIGN_OBJECT) +#define FOR_EACH_FOREIGN_OBJECT_TAG(macro) \ + macro(foreignObject, FOREIGNOBJECT) +#else +#define FOR_EACH_FOREIGN_OBJECT_TAG(macro) +#endif + +#if ENABLE(SVG_USE) +#define FOR_EACH_USE_TAG(macro) \ + macro(use, USE) +#else +#define FOR_EACH_USE_TAG(macro) +#endif + +#define FOR_EACH_TAG(macro) \ + FOR_EACH_ANIMATION_TAG(macro) \ + FOR_EACH_FILTERS_TAG(macro) \ + FOR_EACH_FONTS_TAG(macro) \ + FOR_EACH_FOREIGN_OBJECT_TAG(macro) \ + FOR_EACH_USE_TAG(macro) \ + macro(a, A) \ + macro(altGlyph, ALTGLYPH) \ + macro(circle, CIRCLE) \ + macro(clipPath, CLIPPATH) \ + macro(cursor, CURSOR) \ + macro(defs, DEFS) \ + macro(desc, DESC) \ + macro(ellipse, ELLIPSE) \ + macro(g, G) \ + macro(glyph, GLYPH) \ + macro(image, IMAGE) \ + macro(linearGradient, LINEARGRADIENT) \ + macro(line, LINE) \ + macro(marker, MARKER) \ + macro(mask, MASK) \ + macro(metadata, METADATA) \ + macro(path, PATH) \ + macro(pattern, PATTERN) \ + macro(polyline, POLYLINE) \ + macro(polygon, POLYGON) \ + macro(radialGradient, RADIALGRADIENT) \ + macro(rect, RECT) \ + macro(script, SCRIPT) \ + macro(stop, STOP) \ + macro(style, STYLE) \ + macro(svg, SVG) \ + macro(switch, SWITCH) \ + macro(symbol, SYMBOL) \ + macro(text, TEXT) \ + macro(textPath, TEXTPATH) \ + macro(title, TITLE) \ + macro(tref, TREF) \ + macro(tspan, TSPAN) \ + macro(view, VIEW) \ + // end of macro + +V8ClassIndex::V8WrapperType V8DOMWrapper::svgElementType(SVGElement* element) +{ + typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap; + DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ()); + if (wrapperTypeMap.isEmpty()) { +#define ADD_TO_HASH_MAP(tag, name) \ + wrapperTypeMap.set(#tag, V8ClassIndex::SVG##name##ELEMENT); + FOR_EACH_TAG(ADD_TO_HASH_MAP) +#undef ADD_TO_HASH_MAP + } + + V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl()); + if (!type) + return V8ClassIndex::SVGELEMENT; + return type; +} +#undef FOR_EACH_TAG + +#endif // ENABLE(SVG) + +v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event) +{ + if (!event) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event); + if (!wrapper.IsEmpty()) + return wrapper; + + V8ClassIndex::V8WrapperType type = V8ClassIndex::EVENT; + + if (event->isUIEvent()) { + if (event->isKeyboardEvent()) + type = V8ClassIndex::KEYBOARDEVENT; + else if (event->isTextEvent()) + type = V8ClassIndex::TEXTEVENT; + else if (event->isMouseEvent()) + type = V8ClassIndex::MOUSEEVENT; + else if (event->isWheelEvent()) + type = V8ClassIndex::WHEELEVENT; +#if ENABLE(SVG) + else if (event->isSVGZoomEvent()) + type = V8ClassIndex::SVGZOOMEVENT; +#endif + else + type = V8ClassIndex::UIEVENT; + } else if (event->isMutationEvent()) + type = V8ClassIndex::MUTATIONEVENT; + else if (event->isOverflowEvent()) + type = V8ClassIndex::OVERFLOWEVENT; + else if (event->isMessageEvent()) + type = V8ClassIndex::MESSAGEEVENT; + else if (event->isProgressEvent()) { + if (event->isXMLHttpRequestProgressEvent()) + type = V8ClassIndex::XMLHTTPREQUESTPROGRESSEVENT; + else + type = V8ClassIndex::PROGRESSEVENT; + } else if (event->isWebKitAnimationEvent()) + type = V8ClassIndex::WEBKITANIMATIONEVENT; + else if (event->isWebKitTransitionEvent()) + type = V8ClassIndex::WEBKITTRANSITIONEVENT; +#if ENABLE(WORKERS) + else if (event->isErrorEvent()) + type = V8ClassIndex::ERROREVENT; +#endif + + + v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::EVENT, event); + if (result.IsEmpty()) { + // Instantiation failed. Avoid updating the DOM object map and + // return null which is already handled by callers of this function + // in case the event is NULL. + return v8::Null(); + } + + event->ref(); // fast ref + setJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result)); + + return result; +} + +static const V8ClassIndex::V8WrapperType mapping[] = { + V8ClassIndex::INVALID_CLASS_INDEX, // NONE + V8ClassIndex::INVALID_CLASS_INDEX, // ELEMENT_NODE needs special treatment + V8ClassIndex::ATTR, // ATTRIBUTE_NODE + V8ClassIndex::TEXT, // TEXT_NODE + V8ClassIndex::CDATASECTION, // CDATA_SECTION_NODE + V8ClassIndex::ENTITYREFERENCE, // ENTITY_REFERENCE_NODE + V8ClassIndex::ENTITY, // ENTITY_NODE + V8ClassIndex::PROCESSINGINSTRUCTION, // PROCESSING_INSTRUCTION_NODE + V8ClassIndex::COMMENT, // COMMENT_NODE + V8ClassIndex::INVALID_CLASS_INDEX, // DOCUMENT_NODE needs special treatment + V8ClassIndex::DOCUMENTTYPE, // DOCUMENT_TYPE_NODE + V8ClassIndex::DOCUMENTFRAGMENT, // DOCUMENT_FRAGMENT_NODE + V8ClassIndex::NOTATION, // NOTATION_NODE + V8ClassIndex::NODE, // XPATH_NAMESPACE_NODE +}; + +// Caller checks node is not null. +v8::Handle<v8::Value> V8DOMWrapper::convertNodeToV8Object(Node* node) +{ + if (!node) + return v8::Null(); + + // Find a proxy for this node. + // + // Note that if proxy is found, we might initialize the context which can + // instantiate a document wrapper. Therefore, we get the proxy before + // checking if the node already has a wrapper. + V8Proxy* proxy = 0; + Document* document = node->document(); + if (document) { + Frame* frame = document->frame(); + proxy = V8Proxy::retrieve(frame); + if (proxy) + proxy->initContextIfNeeded(); + } + + DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap(); + v8::Handle<v8::Object> wrapper = domNodeMap.get(node); + if (!wrapper.IsEmpty()) + return wrapper; + + bool isDocument = false; // document type node has special handling + V8ClassIndex::V8WrapperType type; + + Node::NodeType nodeType = node->nodeType(); + if (nodeType == Node::ELEMENT_NODE) { + if (node->isHTMLElement()) + type = htmlElementType(static_cast<HTMLElement*>(node)); +#if ENABLE(SVG) + else if (node->isSVGElement()) + type = svgElementType(static_cast<SVGElement*>(node)); +#endif + else + type = V8ClassIndex::ELEMENT; + } else if (nodeType == Node::DOCUMENT_NODE) { + isDocument = true; + Document* document = static_cast<Document*>(node); + if (document->isHTMLDocument()) + type = V8ClassIndex::HTMLDOCUMENT; +#if ENABLE(SVG) + else if (document->isSVGDocument()) + type = V8ClassIndex::SVGDOCUMENT; +#endif + else + type = V8ClassIndex::DOCUMENT; + } else { + ASSERT(nodeType < sizeof(mapping)/sizeof(mapping[0])); + type = mapping[nodeType]; + ASSERT(type != V8ClassIndex::INVALID_CLASS_INDEX); + } + + v8::Handle<v8::Context> context; + if (proxy) + context = V8Proxy::context(proxy->frame()); + + // Enter the node's context and create the wrapper in that context. + if (!context.IsEmpty()) + context->Enter(); + + v8::Local<v8::Object> result = instantiateV8Object(proxy, type, V8ClassIndex::NODE, node); + + // Exit the node's context if it was entered. + if (!context.IsEmpty()) + context->Exit(); + + if (result.IsEmpty()) { + // If instantiation failed it's important not to add the result + // to the DOM node map. Instead we return an empty handle, which + // should already be handled by callers of this function in case + // the node is NULL. + return result; + } + + node->ref(); + domNodeMap.set(node, v8::Persistent<v8::Object>::New(result)); + + if (isDocument) { + if (proxy) + proxy->updateDocumentWrapper(result); + + if (type == V8ClassIndex::HTMLDOCUMENT) { + // Create marker object and insert it in two internal fields. + // This is used to implement temporary shadowing of + // document.all. + ASSERT(result->InternalFieldCount() == V8Custom::kHTMLDocumentInternalFieldCount); + v8::Local<v8::Object> marker = v8::Object::New(); + result->SetInternalField(V8Custom::kHTMLDocumentMarkerIndex, marker); + result->SetInternalField(V8Custom::kHTMLDocumentShadowIndex, marker); + } + } + + return result; +} + +// A JS object of type EventTarget is limited to a small number of possible classes. +// Check EventTarget.h for new type conversion methods +v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target) +{ + if (!target) + return v8::Null(); + +#if ENABLE(SVG) + SVGElementInstance* instance = target->toSVGElementInstance(); + if (instance) + return convertToV8Object(V8ClassIndex::SVGELEMENTINSTANCE, instance); +#endif + +#if ENABLE(WORKERS) + Worker* worker = target->toWorker(); + if (worker) + return convertToV8Object(V8ClassIndex::WORKER, worker); +#endif // WORKERS + + Node* node = target->toNode(); + if (node) + return convertNodeToV8Object(node); + + if (DOMWindow* domWindow = target->toDOMWindow()) + return convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow); + + // XMLHttpRequest is created within its JS counterpart. + XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest(); + if (xmlHttpRequest) { + v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest); + ASSERT(!wrapper.IsEmpty()); + return wrapper; + } + + // MessagePort is created within its JS counterpart + MessagePort* port = target->toMessagePort(); + if (port) { + v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port); + ASSERT(!wrapper.IsEmpty()); + return wrapper; + } + + XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload(); + if (upload) { + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload); + ASSERT(!wrapper.IsEmpty()); + return wrapper; + } + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + DOMApplicationCache* domAppCache = target->toDOMApplicationCache(); + if (domAppCache) + return convertToV8Object(V8ClassIndex::DOMAPPLICATIONCACHE, domAppCache); +#endif + + ASSERT(0); + return notHandledByInterceptor(); +} + +v8::Handle<v8::Value> V8DOMWrapper::convertEventListenerToV8Object(EventListener* listener) +{ + if (!listener) + return v8::Null(); + + // FIXME: can a user take a lazy event listener and set to other places? + V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener); + return v8listener->getListenerObject(); +} + +v8::Handle<v8::Value> V8DOMWrapper::convertDOMImplementationToV8Object(DOMImplementation* impl) +{ + v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION, V8ClassIndex::DOMIMPLEMENTATION, impl); + if (result.IsEmpty()) { + // If the instantiation failed, we ignore it and return null instead + // of returning an empty handle. + return v8::Null(); + } + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertStyleSheetToV8Object(StyleSheet* sheet) +{ + if (!sheet) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(sheet); + if (!wrapper.IsEmpty()) + return wrapper; + + V8ClassIndex::V8WrapperType type = V8ClassIndex::STYLESHEET; + if (sheet->isCSSStyleSheet()) + type = V8ClassIndex::CSSSTYLESHEET; + + v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::STYLESHEET, sheet); + if (!result.IsEmpty()) { + // Only update the DOM object map if the result is non-empty. + sheet->ref(); + setJSWrapperForDOMObject(sheet, v8::Persistent<v8::Object>::New(result)); + } + + // Add a hidden reference from stylesheet object to its owner node. + Node* ownerNode = sheet->ownerNode(); + if (ownerNode) { + v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(ownerNode)); + result->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex, owner); + } + + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertCSSValueToV8Object(CSSValue* value) +{ + if (!value) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(value); + if (!wrapper.IsEmpty()) + return wrapper; + + V8ClassIndex::V8WrapperType type; + + if (value->isWebKitCSSTransformValue()) + type = V8ClassIndex::WEBKITCSSTRANSFORMVALUE; + else if (value->isValueList()) + type = V8ClassIndex::CSSVALUELIST; + else if (value->isPrimitiveValue()) + type = V8ClassIndex::CSSPRIMITIVEVALUE; +#if ENABLE(SVG) + else if (value->isSVGPaint()) + type = V8ClassIndex::SVGPAINT; + else if (value->isSVGColor()) + type = V8ClassIndex::SVGCOLOR; +#endif + else + type = V8ClassIndex::CSSVALUE; + + v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSVALUE, value); + if (!result.IsEmpty()) { + // Only update the DOM object map if the result is non-empty. + value->ref(); + setJSWrapperForDOMObject(value, v8::Persistent<v8::Object>::New(result)); + } + + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertCSSRuleToV8Object(CSSRule* rule) +{ + if (!rule) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(rule); + if (!wrapper.IsEmpty()) + return wrapper; + + V8ClassIndex::V8WrapperType type; + + switch (rule->type()) { + case CSSRule::STYLE_RULE: + type = V8ClassIndex::CSSSTYLERULE; + break; + case CSSRule::CHARSET_RULE: + type = V8ClassIndex::CSSCHARSETRULE; + break; + case CSSRule::IMPORT_RULE: + type = V8ClassIndex::CSSIMPORTRULE; + break; + case CSSRule::MEDIA_RULE: + type = V8ClassIndex::CSSMEDIARULE; + break; + case CSSRule::FONT_FACE_RULE: + type = V8ClassIndex::CSSFONTFACERULE; + break; + case CSSRule::PAGE_RULE: + type = V8ClassIndex::CSSPAGERULE; + break; + case CSSRule::VARIABLES_RULE: + type = V8ClassIndex::CSSVARIABLESRULE; + break; + case CSSRule::WEBKIT_KEYFRAME_RULE: + type = V8ClassIndex::WEBKITCSSKEYFRAMERULE; + break; + case CSSRule::WEBKIT_KEYFRAMES_RULE: + type = V8ClassIndex::WEBKITCSSKEYFRAMESRULE; + break; + default: // CSSRule::UNKNOWN_RULE + type = V8ClassIndex::CSSRULE; + break; + } + + v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSRULE, rule); + if (!result.IsEmpty()) { + // Only update the DOM object map if the result is non-empty. + rule->ref(); + setJSWrapperForDOMObject(rule, v8::Persistent<v8::Object>::New(result)); + } + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertWindowToV8Object(DOMWindow* window) +{ + if (!window) + return v8::Null(); + // Initializes environment of a frame, and return the global object + // of the frame. + Frame* frame = window->frame(); + if (!frame) + return v8::Handle<v8::Object>(); + + // Special case: Because of evaluateInNewContext() one DOMWindow can have + // multiple contexts and multiple global objects associated with it. When + // code running in one of those contexts accesses the window object, we + // want to return the global object associated with that context, not + // necessarily the first global object associated with that DOMWindow. + v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent(); + v8::Handle<v8::Object> currentGlobal = currentContext->Global(); + v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, currentGlobal); + if (!windowWrapper.IsEmpty()) { + if (convertDOMWrapperToNative<DOMWindow>(windowWrapper) == window) + return currentGlobal; + } + + // Otherwise, return the global object associated with this frame. + v8::Handle<v8::Context> context = V8Proxy::context(frame); + if (context.IsEmpty()) + return v8::Handle<v8::Object>(); + + v8::Handle<v8::Object> global = context->Global(); + ASSERT(!global.IsEmpty()); + return global; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h new file mode 100644 index 0000000..57b3a69 --- /dev/null +++ b/WebCore/bindings/v8/V8DOMWrapper.h @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8DOMWrapper_h +#define V8DOMWrapper_h + +#include "Event.h" +#include "Node.h" +#include "NodeFilter.h" +#include "PlatformString.h" // for WebCore::String +#include "V8CustomBinding.h" +#include "V8Index.h" +#include "V8Utilities.h" +#include <v8.h> + +namespace WebCore { + + // FIXME: This probably aren't all needed. + class CSSRule; + class CSSRuleList; + class CSSStyleDeclaration; + class CSSValue; + class CSSValueList; + class ClientRectList; + class DOMImplementation; + class DOMWindow; + class Document; + class Element; + class Event; + class EventListener; + class EventTarget; + class Frame; + class HTMLCollection; + class HTMLDocument; + class HTMLElement; + class HTMLOptionsCollection; + class MediaList; + class MimeType; + class MimeTypeArray; + class NamedNodeMap; + class Navigator; + class Node; + class NodeFilter; + class NodeList; + class Plugin; + class PluginArray; + class SVGElement; +#if ENABLE(SVG) + class SVGElementInstance; +#endif + class Screen; + class ScriptExecutionContext; +#if ENABLE(DOM_STORAGE) + class Storage; + class StorageEvent; +#endif + class String; + class StyleSheet; + class StyleSheetList; + class V8EventListener; + class V8ObjectEventListener; + class WorkerContext; + + class V8DOMWrapper { + public: +#ifndef NDEBUG + // Checks if a v8 value can be a DOM wrapper + static bool maybeDOMWrapper(v8::Handle<v8::Value>); +#endif + + // Sets contents of a DOM wrapper. + static void setDOMWrapper(v8::Handle<v8::Object>, int type, void* ptr); + + static v8::Handle<v8::Object> lookupDOMWrapper(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) + { + return object.IsEmpty() ? object : object->FindInstanceInPrototypeChain(getTemplate(type)); + } + + // A helper function extract native object pointer from a DOM wrapper + // and cast to the specified type. + template <class C> + static C* convertDOMWrapperToNative(v8::Handle<v8::Object> object) + { + ASSERT(maybeDOMWrapper(object)); + return reinterpret_cast<C*>(object->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex)); + } + + template <class C> + static C* convertDOMWrapperToNode(v8::Handle<v8::Object> object) + { + ASSERT(maybeDOMWrapper(object)); + ASSERT(domWrapperType(object) == V8ClassIndex::NODE); + return convertDOMWrapperToNative<C>(object); + } + + template<typename T> + static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> imp) + { + return convertToV8Object(type, imp.get()); + } + + static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType, void*); + + // Fast-path for Node objects. + static v8::Handle<v8::Value> convertNodeToV8Object(PassRefPtr<Node> node) + { + return convertNodeToV8Object(node.get()); + } + + static v8::Handle<v8::Value> convertNodeToV8Object(Node*); + + template <class C> + static C* convertToNativeObject(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) + { + // Native event listener is per frame, it cannot be handled by this generic function. + ASSERT(type != V8ClassIndex::EVENTLISTENER); + ASSERT(type != V8ClassIndex::EVENTTARGET); + + ASSERT(maybeDOMWrapper(object)); + +#ifndef NDEBUG + const bool typeIsValid = +#define MAKE_CASE(TYPE, NAME) (type != V8ClassIndex::TYPE) && + DOM_NODE_TYPES(MAKE_CASE) +#if ENABLE(SVG) + SVG_NODE_TYPES(MAKE_CASE) +#endif +#undef MAKE_CASE + true; + ASSERT(typeIsValid); +#endif + + return convertDOMWrapperToNative<C>(object); + } + + static V8ClassIndex::V8WrapperType domWrapperType(v8::Handle<v8::Object>); + + static v8::Handle<v8::Value> convertEventToV8Object(PassRefPtr<Event> event) + { + return convertEventToV8Object(event.get()); + } + + static v8::Handle<v8::Value> convertEventToV8Object(Event*); + + static Event* convertToNativeEvent(v8::Handle<v8::Value> jsEvent) + { + if (!isDOMEventWrapper(jsEvent)) + return 0; + return convertDOMWrapperToNative<Event>(v8::Handle<v8::Object>::Cast(jsEvent)); + } + + static v8::Handle<v8::Value> convertEventTargetToV8Object(PassRefPtr<EventTarget> eventTarget) + { + return convertEventTargetToV8Object(eventTarget.get()); + } + + static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*); + + // Wrap and unwrap JS event listeners. + static v8::Handle<v8::Value> convertEventListenerToV8Object(PassRefPtr<Event> eventListener) + { + return convertEventListenerToV8Object(eventListener.get()); + } + + static v8::Handle<v8::Value> convertEventListenerToV8Object(EventListener*); + + // DOMImplementation is a singleton and it is handled in a special + // way. A wrapper is generated per document and stored in an + // internal field of the document. + static v8::Handle<v8::Value> convertDOMImplementationToV8Object(DOMImplementation*); + + // Wrap JS node filter in C++. + static PassRefPtr<NodeFilter> wrapNativeNodeFilter(v8::Handle<v8::Value>); + + static v8::Persistent<v8::FunctionTemplate> getTemplate(V8ClassIndex::V8WrapperType); + static v8::Local<v8::Function> getConstructorForContext(V8ClassIndex::V8WrapperType, v8::Handle<v8::Context>); + static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value> objectPrototype); + static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, DOMWindow*); + static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, WorkerContext*); + + // Checks whether a DOM object has a JS wrapper. + static bool domObjectHasJSWrapper(void*); + // Set JS wrapper of a DOM object, the caller in charge of increase ref. + static void setJSWrapperForDOMObject(void*, v8::Persistent<v8::Object>); + static void setJSWrapperForActiveDOMObject(void*, v8::Persistent<v8::Object>); + static void setJSWrapperForDOMNode(Node*, v8::Persistent<v8::Object>); + + // Check whether a V8 value is a wrapper of type |classType|. + static bool isWrapperOfType(v8::Handle<v8::Value>, V8ClassIndex::V8WrapperType); + + static void* convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value>); + + // Check whether a V8 value is a DOM Event wrapper. + static bool isDOMEventWrapper(v8::Handle<v8::Value>); + + static v8::Handle<v8::Value> convertStyleSheetToV8Object(StyleSheet*); + static v8::Handle<v8::Value> convertCSSValueToV8Object(CSSValue*); + static v8::Handle<v8::Value> convertCSSRuleToV8Object(CSSRule*); + // Returns the JS wrapper of a window object, initializes the environment + // of the window frame if needed. + static v8::Handle<v8::Value> convertWindowToV8Object(DOMWindow*); + +#if ENABLE(SVG) + static v8::Handle<v8::Value> convertSVGElementInstanceToV8Object(SVGElementInstance*); + static v8::Handle<v8::Value> convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType, void*); +#endif + + private: + // Set hidden references in a DOMWindow object of a frame. + static void setHiddenWindowReference(Frame*, const int internalIndex, v8::Handle<v8::Object>); + + static V8ClassIndex::V8WrapperType htmlElementType(HTMLElement*); +#if ENABLE(SVG) + static V8ClassIndex::V8WrapperType svgElementType(SVGElement*); +#endif + + // The first V8WrapperType specifies the function descriptor + // used to create JS object. The second V8WrapperType specifies + // the actual type of the void* for type casting. + // For example, a HTML element has HTMLELEMENT for the first V8WrapperType, but always + // use NODE as the second V8WrapperType. JS wrapper stores the second + // V8WrapperType and the void* as internal fields. + static v8::Local<v8::Object> instantiateV8Object(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl) + { + return instantiateV8Object(NULL, descType, cptrType, impl); + } + + static v8::Local<v8::Object> instantiateV8Object(V8Proxy*, V8ClassIndex::V8WrapperType, V8ClassIndex::V8WrapperType, void*); + }; + +} + +#endif // V8DOMWrapper_h diff --git a/WebCore/bindings/v8/custom/V8DOMStringListCustom.cpp b/WebCore/bindings/v8/V8DataGridDataSource.cpp index 52d4399..6fff1f5 100644 --- a/WebCore/bindings/v8/custom/V8DOMStringListCustom.cpp +++ b/WebCore/bindings/v8/V8DataGridDataSource.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2009 Google Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,34 +29,37 @@ */ #include "config.h" -#include "DOMStringList.h" -#include "V8Binding.h" -#include "V8CustomBinding.h" -#include "V8Proxy.h" +#if ENABLE(DATAGRID) + +#include "V8DataGridDataSource.h" + +#include "Document.h" +#include "Frame.h" +#include "HTMLDataGridElement.h" +#include "V8HTMLDataGridElement.h" + namespace WebCore { -INDEXED_PROPERTY_GETTER(DOMStringList) +V8DataGridDataSource::V8DataGridDataSource(v8::Handle<v8::Value> dataSource, Frame* frame) + : m_dataSource(v8::Persistent<v8::Value>::New(dataSource)) + , m_frame(frame) { - INC_STATS("DOM.DOMStringList.IndexedPropertyGetter"); - DOMStringList* imp = V8Proxy::DOMWrapperToNative<DOMStringList>(info.Holder()); - return v8String(imp->item(index)); +#ifndef NDEBUG + V8GCController::registerGlobalHandle(DATASOURCE, this, m_dataSource); +#endif } -CALLBACK_FUNC_DECL(DOMStringListItem) +V8DataGridDataSource::~V8DataGridDataSource() { - INC_STATS("DOM.DOMStringListItem()"); - if (!args.Length()) - return v8::Null(); - - uint32_t index = args[0]->Uint32Value(); - - DOMStringList* imp = V8Proxy::DOMWrapperToNative<DOMStringList>(args.Holder()); - if (index >= imp->length()) - return v8::Null(); - - return v8String(imp->item(index)); +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_dataSource); +#endif + m_dataSource.Dispose(); + m_dataSource.Clear(); } } // namespace WebCore + +#endif // ENABLE(DATAGRID) diff --git a/WebCore/bindings/v8/V8DataGridDataSource.h b/WebCore/bindings/v8/V8DataGridDataSource.h new file mode 100644 index 0000000..7f6d8d8 --- /dev/null +++ b/WebCore/bindings/v8/V8DataGridDataSource.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef V8DataGridDataSource_h +#define V8DataGridDataSource_h + +#if ENABLE(DATAGRID) + +#include "DataGridDataSource.h" +#include <v8.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class Frame; +class HTMLDataGridElement; + +class V8DataGridDataSource : public DataGridDataSource { +public: + static PassRefPtr<V8DataGridDataSource> create(v8::Handle<v8::Value> dataSource, Frame* frame) + { + return adoptRef(new V8DataGridDataSource(dataSource, frame)); + } + + virtual ~V8DataGridDataSource(); + + virtual bool isJSDataGridDataSource() const { return true; } + v8::Handle<v8::Value> jsDataSource() const { return m_dataSource; } + +private: + V8DataGridDataSource(v8::Handle<v8::Value>, Frame*); + + v8::Persistent<v8::Value> m_dataSource; + RefPtr<Frame> m_frame; +}; + +inline V8DataGridDataSource* asV8DataGridDataSource(DataGridDataSource* dataSource) +{ + ASSERT(dataSource->isJSDataGridDataSource()); + return static_cast<V8DataGridDataSource*>(dataSource); +} + +inline const V8DataGridDataSource* asV8DataGridDataSource(const DataGridDataSource* dataSource) +{ + ASSERT(dataSource->isJSDataGridDataSource()); + return static_cast<const V8DataGridDataSource*>(dataSource); +} + +} // namespace WebCore + +#endif // ENABLE(DATAGRID) +#endif // V8DataGridDataSource_h diff --git a/WebCore/bindings/v8/V8EventListenerList.cpp b/WebCore/bindings/v8/V8EventListenerList.cpp index df60028..c9aaa12 100644 --- a/WebCore/bindings/v8/V8EventListenerList.cpp +++ b/WebCore/bindings/v8/V8EventListenerList.cpp @@ -182,4 +182,14 @@ V8EventListener* V8EventListenerList::find(v8::Local<v8::Object> object, bool is return 0; } +PassRefPtr<V8EventListener> V8EventListenerList::findWrapper(v8::Local<v8::Value> object, bool isAttribute) +{ + ASSERT(v8::Context::InContext()); + if (!object->IsObject()) + return 0; + + // FIXME: Should this be v8::Local<v8::Object>::Cast instead? + return find(object->ToObject(), isAttribute); +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/V8EventListenerList.h b/WebCore/bindings/v8/V8EventListenerList.h index d7799b8..4255050 100644 --- a/WebCore/bindings/v8/V8EventListenerList.h +++ b/WebCore/bindings/v8/V8EventListenerList.h @@ -35,7 +35,10 @@ #include <wtf/Vector.h> #include <wtf/HashMap.h> +#include "PassRefPtr.h" + namespace WebCore { + class Frame; class V8EventListener; class V8EventListenerListIterator; @@ -67,6 +70,10 @@ namespace WebCore { void clear(); size_t size() { return m_table.size(); } + PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value>, bool isAttribute); + template<typename WrapperType> + PassRefPtr<V8EventListener> findOrCreateWrapper(Frame*, v8::Local<v8::Value>, bool isAttribute); + private: ListenerMultiMap m_table; @@ -93,6 +100,25 @@ namespace WebCore { size_t m_vectorIndex; }; + template<typename WrapperType> + PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(Frame* frame, v8::Local<v8::Value> object, bool isAttribute) + { + ASSERT(v8::Context::InContext()); + if (!object->IsObject()) + return 0; + + // FIXME: Should this be v8::Local<v8::Object>::Cast instead? + V8EventListener* wrapper = find(object->ToObject(), isAttribute); + if (wrapper) + return wrapper; + + // Create a new one, and add to cache. + RefPtr<WrapperType> newListener = WrapperType::create(frame, v8::Local<v8::Object>::Cast(object), isAttribute); + add(newListener.get()); + + return newListener; + }; + } // namespace WebCore #endif // V8EventListenerList_h diff --git a/WebCore/bindings/v8/V8GCController.cpp b/WebCore/bindings/v8/V8GCController.cpp new file mode 100644 index 0000000..1b7c5ad --- /dev/null +++ b/WebCore/bindings/v8/V8GCController.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8GCController.h" + +#include "DOMDataStore.h" +#include "DOMObjectsInclude.h" +#include "V8DOMMap.h" +#include "V8Index.h" +#include "V8Proxy.h" + +#include <algorithm> +#include <utility> +#include <v8.h> +#include <v8-debug.h> +#include <wtf/HashMap.h> +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> + +namespace WebCore { + +#ifndef NDEBUG +// Keeps track of global handles created (not JS wrappers +// of DOM objects). Often these global handles are source +// of leaks. +// +// If you want to let a C++ object hold a persistent handle +// to a JS object, you should register the handle here to +// keep track of leaks. +// +// When creating a persistent handle, call: +// +// #ifndef NDEBUG +// V8GCController::registerGlobalHandle(type, host, handle); +// #endif +// +// When releasing the handle, call: +// +// #ifndef NDEBUG +// V8GCController::unregisterGlobalHandle(type, host, handle); +// #endif +// +typedef HashMap<v8::Value*, GlobalHandleInfo*> GlobalHandleMap; + +static GlobalHandleMap& globalHandleMap() +{ + DEFINE_STATIC_LOCAL(GlobalHandleMap, staticGlobalHandleMap, ()); + return staticGlobalHandleMap; +} + +// The function is the place to set the break point to inspect +// live global handles. Leaks are often come from leaked global handles. +static void enumerateGlobalHandles() +{ + for (GlobalHandleMap::iterator it = globalHandleMap().begin(), end = globalHandleMap().end(); it != end; ++it) { + GlobalHandleInfo* info = it->second; + UNUSED_PARAM(info); + v8::Value* handle = it->first; + UNUSED_PARAM(handle); + } +} + +void V8GCController::registerGlobalHandle(GlobalHandleType type, void* host, v8::Persistent<v8::Value> handle) +{ + ASSERT(!globalHandleMap().contains(*handle)); + globalHandleMap().set(*handle, new GlobalHandleInfo(host, type)); +} + +void V8GCController::unregisterGlobalHandle(void* host, v8::Persistent<v8::Value> handle) +{ + ASSERT(globalHandleMap().contains(*handle)); + GlobalHandleInfo* info = globalHandleMap().take(*handle); + ASSERT(info->m_host == host); + delete info; +} +#endif // ifndef NDEBUG + +typedef HashMap<Node*, v8::Object*> DOMNodeMap; +typedef HashMap<void*, v8::Object*> DOMObjectMap; + +#ifndef NDEBUG + +static void enumerateDOMObjectMap(DOMObjectMap& wrapperMap) +{ + for (DOMObjectMap::iterator it = wrapperMap.begin(), end = wrapperMap.end(); it != end; ++it) { + v8::Persistent<v8::Object> wrapper(it->second); + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + void* object = it->first; + UNUSED_PARAM(type); + UNUSED_PARAM(object); + } +} + +class DOMObjectVisitor : public DOMWrapperMap<void>::Visitor { +public: + void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) + { + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + UNUSED_PARAM(type); + UNUSED_PARAM(object); + } +}; + +class EnsureWeakDOMNodeVisitor : public DOMWrapperMap<Node>::Visitor { +public: + void visitDOMWrapper(Node* object, v8::Persistent<v8::Object> wrapper) + { + UNUSED_PARAM(object); + ASSERT(wrapper.IsWeak()); + } +}; + +#endif // NDEBUG + +// A map from a DOM node to its JS wrapper, the wrapper +// is kept as a strong reference to survive GCs. +static DOMObjectMap& gcProtectedMap() +{ + DEFINE_STATIC_LOCAL(DOMObjectMap, staticGcProtectedMap, ()); + return staticGcProtectedMap; +} + +void V8GCController::gcProtect(void* domObject) +{ + if (!domObject) + return; + if (gcProtectedMap().contains(domObject)) + return; + if (!getDOMObjectMap().contains(domObject)) + return; + + // Create a new (strong) persistent handle for the object. + v8::Persistent<v8::Object> wrapper = getDOMObjectMap().get(domObject); + if (wrapper.IsEmpty()) + return; + + gcProtectedMap().set(domObject, *v8::Persistent<v8::Object>::New(wrapper)); +} + +void V8GCController::gcUnprotect(void* domObject) +{ + if (!domObject) + return; + if (!gcProtectedMap().contains(domObject)) + return; + + // Dispose the strong reference. + v8::Persistent<v8::Object> wrapper(gcProtectedMap().take(domObject)); + wrapper.Dispose(); +} + +class GCPrologueVisitor : public DOMWrapperMap<void>::Visitor { +public: + void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) + { + ASSERT(wrapper.IsWeak()); + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: { \ + NAME* impl = static_cast<NAME*>(object); \ + if (impl->hasPendingActivity()) \ + wrapper.ClearWeak(); \ + break; \ + } + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: + ASSERT_NOT_REACHED(); +#undef MAKE_CASE + } + + // Additional handling of message port ensuring that entangled ports also + // have their wrappers entangled. This should ideally be handled when the + // ports are actually entangled in MessagePort::entangle, but to avoid + // forking MessagePort.* this is postponed to GC time. Having this postponed + // has the drawback that the wrappers are "entangled/unentangled" for each + // GC even though their entaglement most likely is still the same. + if (type == V8ClassIndex::MESSAGEPORT) { + // Get the port and its entangled port. + MessagePort* port1 = static_cast<MessagePort*>(object); + MessagePort* port2 = port1->locallyEntangledPort(); + + // If we are remotely entangled, then mark this object as reachable + // (we can't determine reachability directly as the remote object is + // out-of-proc). + if (port1->isEntangled() && !port2) + wrapper.ClearWeak(); + + if (port2) { + // As ports are always entangled in pairs only perform the entanglement + // once for each pair (see ASSERT in MessagePort::unentangle()). + if (port1 < port2) { + v8::Handle<v8::Value> port1Wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port1); + v8::Handle<v8::Value> port2Wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port2); + ASSERT(port1Wrapper->IsObject()); + v8::Handle<v8::Object>::Cast(port1Wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, port2Wrapper); + ASSERT(port2Wrapper->IsObject()); + v8::Handle<v8::Object>::Cast(port2Wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, port1Wrapper); + } + } else { + // Remove the wrapper entanglement when a port is not entangled. + if (V8DOMWrapper::domObjectHasJSWrapper(port1)) { + v8::Handle<v8::Value> wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port1); + ASSERT(wrapper->IsObject()); + v8::Handle<v8::Object>::Cast(wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, v8::Undefined()); + } + } + } +} +}; + +class GrouperItem { +public: + GrouperItem(uintptr_t groupId, Node* node, v8::Persistent<v8::Object> wrapper) + : m_groupId(groupId) + , m_node(node) + , m_wrapper(wrapper) + { + } + + uintptr_t groupId() const { return m_groupId; } + Node* node() const { return m_node; } + v8::Persistent<v8::Object> wrapper() const { return m_wrapper; } + +private: + uintptr_t m_groupId; + Node* m_node; + v8::Persistent<v8::Object> m_wrapper; +}; + +bool operator<(const GrouperItem& a, const GrouperItem& b) +{ + return a.groupId() < b.groupId(); +} + +typedef Vector<GrouperItem> GrouperList; + +class ObjectGrouperVisitor : public DOMWrapperMap<Node>::Visitor { +public: + ObjectGrouperVisitor() + { + // FIXME: grouper_.reserveCapacity(node_map.size()); ? + } + + void visitDOMWrapper(Node* node, v8::Persistent<v8::Object> wrapper) + { + + // If the node is in document, put it in the ownerDocument's object group. + // + // If an image element was created by JavaScript "new Image", + // it is not in a document. However, if the load event has not + // been fired (still onloading), it is treated as in the document. + // + // Otherwise, the node is put in an object group identified by the root + // element of the tree to which it belongs. + uintptr_t groupId; + if (node->inDocument() || (node->hasTagName(HTMLNames::imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())) + groupId = reinterpret_cast<uintptr_t>(node->document()); + else { + Node* root = node; + while (root->parent()) + root = root->parent(); + + // If the node is alone in its DOM tree (doesn't have a parent or any + // children) then the group will be filtered out later anyway. + if (root == node && !node->hasChildNodes()) + return; + + groupId = reinterpret_cast<uintptr_t>(root); + } + m_grouper.append(GrouperItem(groupId, node, wrapper)); + } + + void applyGrouping() + { + // Group by sorting by the group id. + std::sort(m_grouper.begin(), m_grouper.end()); + + // FIXME Should probably work in iterators here, but indexes were easier for my simple mind. + for (size_t i = 0; i < m_grouper.size(); ) { + // Seek to the next key (or the end of the list). + size_t nextKeyIndex = m_grouper.size(); + for (size_t j = i; j < m_grouper.size(); ++j) { + if (m_grouper[i].groupId() != m_grouper[j].groupId()) { + nextKeyIndex = j; + break; + } + } + + ASSERT(nextKeyIndex > i); + + // We only care about a group if it has more than one object. If it only + // has one object, it has nothing else that needs to be kept alive. + if (nextKeyIndex - i <= 1) { + i = nextKeyIndex; + continue; + } + + Vector<v8::Persistent<v8::Value> > group; + group.reserveCapacity(nextKeyIndex - i); + for (; i < nextKeyIndex; ++i) { + Node* node = m_grouper[i].node(); + v8::Persistent<v8::Value> wrapper = m_grouper[i].wrapper(); + if (!wrapper.IsEmpty()) + group.append(wrapper); + /* FIXME: Re-enabled this code to avoid GCing these wrappers! + Currently this depends on looking up the wrapper + during a GC, but we don't know which isolated world + we're in, so it's unclear which map to look in... + + // If the node is styled and there is a wrapper for the inline + // style declaration, we need to keep that style declaration + // wrapper alive as well, so we add it to the object group. + if (node->isStyledElement()) { + StyledElement* element = reinterpret_cast<StyledElement*>(node); + CSSStyleDeclaration* style = element->inlineStyleDecl(); + if (style != NULL) { + wrapper = getDOMObjectMap().get(style); + if (!wrapper.IsEmpty()) + group.append(wrapper); + } + } + */ + } + + if (group.size() > 1) + v8::V8::AddObjectGroup(&group[0], group.size()); + + ASSERT(i == nextKeyIndex); + } + } + +private: + GrouperList m_grouper; +}; + +// Create object groups for DOM tree nodes. +void V8GCController::gcPrologue() +{ + v8::HandleScope scope; + +#ifndef NDEBUG + DOMObjectVisitor domObjectVisitor; + visitDOMObjectsInCurrentThread(&domObjectVisitor); +#endif + + // Run through all objects with possible pending activity making their + // wrappers non weak if there is pending activity. + GCPrologueVisitor prologueVisitor; + visitActiveDOMObjectsInCurrentThread(&prologueVisitor); + + // Create object groups. + ObjectGrouperVisitor objectGrouperVisitor; + visitDOMNodesInCurrentThread(&objectGrouperVisitor); + objectGrouperVisitor.applyGrouping(); +} + +class GCEpilogueVisitor : public DOMWrapperMap<void>::Visitor { +public: + void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) + { + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: { \ + NAME* impl = static_cast<NAME*>(object); \ + if (impl->hasPendingActivity()) { \ + ASSERT(!wrapper.IsWeak()); \ + wrapper.MakeWeak(impl, &DOMDataStore::weakActiveDOMObjectCallback); \ + } \ + break; \ + } +ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: + ASSERT_NOT_REACHED(); +#undef MAKE_CASE + } + + if (type == V8ClassIndex::MESSAGEPORT) { + MessagePort* port1 = static_cast<MessagePort*>(object); + MessagePort* port2 = port1->locallyEntangledPort(); + if (port1->isEntangled() && !port2) { + // We marked this port as reachable in GCPrologueVisitor. Undo this now since the + // port could be not reachable in the future if it gets disentangled (and also + // GCPrologueVisitor expects to see all handles marked as weak). + wrapper.MakeWeak(port1, &DOMDataStore::weakActiveDOMObjectCallback); + } + } + } +}; + +void V8GCController::gcEpilogue() +{ + v8::HandleScope scope; + + // Run through all objects with pending activity making their wrappers weak + // again. + GCEpilogueVisitor epilogueVisitor; + visitActiveDOMObjectsInCurrentThread(&epilogueVisitor); + +#ifndef NDEBUG + // Check all survivals are weak. + DOMObjectVisitor domObjectVisitor; + visitDOMObjectsInCurrentThread(&domObjectVisitor); + + EnsureWeakDOMNodeVisitor weakDOMNodeVisitor; + visitDOMNodesInCurrentThread(&weakDOMNodeVisitor); + + enumerateDOMObjectMap(gcProtectedMap()); + enumerateGlobalHandles(); +#endif +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8GCController.h b/WebCore/bindings/v8/V8GCController.h new file mode 100644 index 0000000..7441bf0 --- /dev/null +++ b/WebCore/bindings/v8/V8GCController.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8GCController_h +#define V8GCController_h + +#include <v8.h> + +namespace WebCore { + +#ifndef NDEBUG + +#define GlobalHandleTypeList(V) \ + V(PROXY) \ + V(NPOBJECT) \ + V(SCHEDULED_ACTION) \ + V(EVENT_LISTENER) \ + V(NODE_FILTER) \ + V(SCRIPTINSTANCE) \ + V(SCRIPTVALUE) \ + V(DATASOURCE) + + + // Host information of persistent handles. + enum GlobalHandleType { +#define ENUM(name) name, + GlobalHandleTypeList(ENUM) +#undef ENUM + }; + + class GlobalHandleInfo { + public: + GlobalHandleInfo(void* host, GlobalHandleType type) : m_host(host), m_type(type) { } + void* m_host; + GlobalHandleType m_type; + }; + +#endif // NDEBUG + + class V8GCController { + public: + // Protect/Unprotect JS wrappers of a DOM object. + static void gcProtect(void* domObject); + static void gcUnprotect(void* domObject); + +#ifndef NDEBUG + // For debugging and leak detection purpose. + static void registerGlobalHandle(GlobalHandleType, void*, v8::Persistent<v8::Value>); + static void unregisterGlobalHandle(void*, v8::Persistent<v8::Value>); +#endif + + static void gcPrologue(); + static void gcEpilogue(); + }; + +} + +#endif // V8GCController_h diff --git a/WebCore/bindings/v8/V8Helpers.cpp b/WebCore/bindings/v8/V8Helpers.cpp new file mode 100644 index 0000000..a690017 --- /dev/null +++ b/WebCore/bindings/v8/V8Helpers.cpp @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2008, 2009 Google Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Google Inc. nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "config.h" +#include "V8Helpers.h" + +#include "DOMWindow.h" +#include "NPV8Object.h" +#include "V8Index.h" +#include "V8Proxy.h" + +namespace WebCore { + +void wrapNPObject(v8::Handle<v8::Object> object, NPObject* npObject) +{ + V8DOMWrapper::setDOMWrapper(object, V8ClassIndex::NPOBJECT, npObject); +} + +v8::Local<v8::Context> toV8Context(NPP npp, NPObject* npObject) +{ + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + return V8Proxy::mainWorldContext(object->rootObject->frame()); +} + +V8Proxy* toV8Proxy(NPObject* npObject) +{ + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + Frame* frame = object->rootObject->frame(); + return V8Proxy::retrieve(frame); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Helpers.h b/WebCore/bindings/v8/V8Helpers.h new file mode 100644 index 0000000..469833e --- /dev/null +++ b/WebCore/bindings/v8/V8Helpers.h @@ -0,0 +1,49 @@ +/* +* Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Google Inc. nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef V8Helpers_h +#define V8Helpers_h + +#include "npruntime.h" +#include <v8.h> + +namespace WebCore { + class V8Proxy; + + // Associates an NPObject with a V8 object. + void wrapNPObject(v8::Handle<v8::Object>, NPObject*); + + v8::Local<v8::Context> toV8Context(NPP, NPObject*); + + V8Proxy* toV8Proxy(NPObject*); + +} // namespace WebCore + +#endif // V8Helpers_h diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.cpp b/WebCore/bindings/v8/V8HiddenPropertyName.cpp new file mode 100644 index 0000000..16ac232 --- /dev/null +++ b/WebCore/bindings/v8/V8HiddenPropertyName.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8HiddenPropertyName.h" + +namespace WebCore { + +v8::Handle<v8::String> V8HiddenPropertyName::objectPrototype() +{ + static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::objectPrototype"); + + return *string; +} + +v8::Handle<v8::String> V8HiddenPropertyName::isolatedWorld() +{ + static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::isolatedWorld"); + + return *string; +} + +v8::Persistent<v8::String>* V8HiddenPropertyName::createString(const char* key) +{ + return new v8::Persistent<v8::String>(v8::Persistent<v8::String>::New(v8::String::NewSymbol(key))); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.h b/WebCore/bindings/v8/V8HiddenPropertyName.h new file mode 100644 index 0000000..874b525 --- /dev/null +++ b/WebCore/bindings/v8/V8HiddenPropertyName.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8HiddenPropertyName_h +#define V8HiddenPropertyName_h + +#include <v8.h> + +namespace WebCore { + + class V8HiddenPropertyName { + public: + static v8::Handle<v8::String> objectPrototype(); + static v8::Handle<v8::String> isolatedWorld(); + + private: + static v8::Persistent<v8::String>* createString(const char* key); + }; + +} + +#endif // V8HiddenPropertyName_h diff --git a/WebCore/bindings/v8/V8Index.cpp b/WebCore/bindings/v8/V8Index.cpp new file mode 100644 index 0000000..8ac3669 --- /dev/null +++ b/WebCore/bindings/v8/V8Index.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8Index.h" + +#include "V8Attr.h" +#include "V8BarInfo.h" +#include "V8CanvasRenderingContext2D.h" +#include "V8CanvasGradient.h" +#include "V8CanvasPattern.h" +#include "V8CanvasPixelArray.h" +#include "V8CDATASection.h" +#include "V8CharacterData.h" +#include "V8ClientRect.h" +#include "V8ClientRectList.h" +#include "V8Clipboard.h" +#include "V8Comment.h" +#include "V8Console.h" +#include "V8Counter.h" +#include "V8CSSStyleDeclaration.h" +#include "V8CSSRule.h" +#include "V8CSSStyleRule.h" +#include "V8CSSCharsetRule.h" +#include "V8CSSImportRule.h" +#include "V8CSSMediaRule.h" +#include "V8CSSFontFaceRule.h" +#include "V8CSSPageRule.h" +#include "V8CSSRuleList.h" +#include "V8CSSPrimitiveValue.h" +#include "V8CSSValue.h" +#include "V8CSSValueList.h" +#include "V8CSSStyleSheet.h" +#include "V8CSSVariablesDeclaration.h" +#include "V8CSSVariablesRule.h" +#include "V8DataGridColumn.h" +#include "V8DataGridColumnList.h" +#include "V8Database.h" +#include "V8Document.h" +#include "V8DocumentFragment.h" +#include "V8DocumentType.h" +#include "V8Element.h" +#include "V8Entity.h" +#include "V8EntityReference.h" +#include "V8File.h" +#include "V8FileList.h" +#include "V8History.h" +#include "V8HTMLAllCollection.h" +#include "V8HTMLCanvasElement.h" +#include "V8HTMLCollection.h" +#include "V8HTMLDocument.h" +#include "V8HTMLElement.h" +#include "V8HTMLOptionsCollection.h" +#include "V8HTMLAnchorElement.h" +#include "V8HTMLAppletElement.h" +#include "V8HTMLAreaElement.h" +#include "V8HTMLBaseElement.h" +#include "V8HTMLBaseFontElement.h" +#include "V8HTMLBlockquoteElement.h" +#include "V8HTMLBodyElement.h" +#include "V8HTMLBRElement.h" +#include "V8HTMLButtonElement.h" +#include "V8HTMLCanvasElement.h" +#include "V8HTMLModElement.h" +#include "V8HTMLDataGridCellElement.h" +#include "V8HTMLDataGridColElement.h" +#include "V8HTMLDataGridElement.h" +#include "V8HTMLDataGridRowElement.h" +#include "V8HTMLDirectoryElement.h" +#include "V8HTMLDivElement.h" +#include "V8HTMLDListElement.h" +#include "V8HTMLEmbedElement.h" +#include "V8HTMLFieldSetElement.h" +#include "V8HTMLFormElement.h" +#include "V8HTMLFontElement.h" +#include "V8HTMLFrameElement.h" +#include "V8HTMLFrameSetElement.h" +#include "V8HTMLHeadingElement.h" +#include "V8HTMLHeadElement.h" +#include "V8HTMLHRElement.h" +#include "V8HTMLHtmlElement.h" +#include "V8HTMLIFrameElement.h" +#include "V8HTMLImageElement.h" +#include "V8HTMLInputElement.h" +#include "V8HTMLIsIndexElement.h" +#include "V8HTMLLabelElement.h" +#include "V8HTMLLegendElement.h" +#include "V8HTMLLIElement.h" +#include "V8HTMLLinkElement.h" +#include "V8HTMLMapElement.h" +#include "V8HTMLMarqueeElement.h" +#include "V8HTMLMenuElement.h" +#include "V8HTMLMetaElement.h" +#include "V8HTMLObjectElement.h" +#include "V8HTMLOListElement.h" +#include "V8HTMLOptGroupElement.h" +#include "V8HTMLOptionElement.h" +#include "V8HTMLParagraphElement.h" +#include "V8HTMLParamElement.h" +#include "V8HTMLPreElement.h" +#include "V8HTMLQuoteElement.h" +#include "V8HTMLScriptElement.h" +#include "V8HTMLSelectElement.h" +#include "V8HTMLStyleElement.h" +#include "V8HTMLTableCaptionElement.h" +#include "V8HTMLTableColElement.h" +#include "V8HTMLTableElement.h" +#include "V8HTMLTableSectionElement.h" +#include "V8HTMLTableCellElement.h" +#include "V8HTMLTableRowElement.h" +#include "V8HTMLTextAreaElement.h" +#include "V8HTMLTitleElement.h" +#include "V8HTMLUListElement.h" +#include "V8ImageData.h" +#include "V8InspectorBackend.h" +#include "V8Media.h" +#include "V8MediaList.h" +#include "V8MessageChannel.h" +#include "V8MessageEvent.h" +#include "V8MessagePort.h" +#include "V8NamedNodeMap.h" +#include "V8Node.h" +#include "V8NodeList.h" +#include "V8NodeFilter.h" +#include "V8Notation.h" +#include "V8ProcessingInstruction.h" +#include "V8ProgressEvent.h" +#include "V8StyleSheet.h" +#include "V8Text.h" +#include "V8TextEvent.h" +#include "V8DOMCoreException.h" +#include "V8DOMParser.h" +#include "V8DOMWindow.h" +#include "V8ErrorEvent.h" +#include "V8Event.h" +#include "V8EventException.h" +#include "V8KeyboardEvent.h" +#include "V8MouseEvent.h" +#include "V8ValidityState.h" +#include "V8WebKitAnimationEvent.h" +#include "V8WebKitCSSKeyframeRule.h" +#include "V8WebKitCSSKeyframesRule.h" +#include "V8WebKitCSSMatrix.h" +#include "V8WebKitCSSTransformValue.h" +#include "V8WebKitPoint.h" +#include "V8WebKitTransitionEvent.h" +#include "V8WheelEvent.h" +#include "V8UIEvent.h" +#include "V8MutationEvent.h" +#include "V8OverflowEvent.h" +#include "V8Location.h" +#include "V8Screen.h" +#include "V8DOMSelection.h" +#include "V8Navigator.h" +#include "V8MimeType.h" +#include "V8MimeTypeArray.h" +#include "V8Plugin.h" +#include "V8PluginArray.h" +#include "V8Range.h" +#include "V8RangeException.h" +#include "V8Rect.h" +#include "V8SQLError.h" +#include "V8SQLResultSet.h" +#include "V8SQLResultSetRowList.h" +#include "V8SQLTransaction.h" +#include "V8NodeIterator.h" +#include "V8TextMetrics.h" +#include "V8TreeWalker.h" +#include "V8StyleSheetList.h" +#include "V8DOMImplementation.h" +#include "V8XPathResult.h" +#include "V8XPathException.h" +#include "V8XPathExpression.h" +#include "V8XPathNSResolver.h" +#include "V8XMLHttpRequest.h" +#include "V8XMLHttpRequestException.h" +#include "V8XMLHttpRequestProgressEvent.h" +#include "V8XMLHttpRequestUpload.h" +#include "V8XMLSerializer.h" +#include "V8XPathEvaluator.h" +#include "V8XSLTProcessor.h" +#include "V8RGBColor.h" + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "V8DOMApplicationCache.h" +#endif + +#if ENABLE(DOM_STORAGE) +#include "V8Storage.h" +#include "V8StorageEvent.h" +#endif + +#if ENABLE(SVG_ANIMATION) +#include "V8SVGAnimateColorElement.h" +#include "V8SVGAnimateElement.h" +#include "V8SVGAnimateTransformElement.h" +#include "V8SVGAnimationElement.h" +#include "V8SVGSetElement.h" +#endif + +#if ENABLE(SVG_FILTERS) +#include "V8SVGComponentTransferFunctionElement.h" +#include "V8SVGFEBlendElement.h" +#include "V8SVGFEColorMatrixElement.h" +#include "V8SVGFEComponentTransferElement.h" +#include "V8SVGFECompositeElement.h" +#include "V8SVGFEDiffuseLightingElement.h" +#include "V8SVGFEDisplacementMapElement.h" +#include "V8SVGFEDistantLightElement.h" +#include "V8SVGFEFloodElement.h" +#include "V8SVGFEFuncAElement.h" +#include "V8SVGFEFuncBElement.h" +#include "V8SVGFEFuncGElement.h" +#include "V8SVGFEFuncRElement.h" +#include "V8SVGFEGaussianBlurElement.h" +#include "V8SVGFEImageElement.h" +#include "V8SVGFEMergeElement.h" +#include "V8SVGFEMergeNodeElement.h" +#include "V8SVGFEOffsetElement.h" +#include "V8SVGFEPointLightElement.h" +#include "V8SVGFESpecularLightingElement.h" +#include "V8SVGFESpotLightElement.h" +#include "V8SVGFETileElement.h" +#include "V8SVGFETurbulenceElement.h" +#include "V8SVGFilterElement.h" +#endif + +#if ENABLE(SVG_FONTS) +#include "V8SVGDefinitionSrcElement.h" +#include "V8SVGFontFaceElement.h" +#include "V8SVGFontFaceFormatElement.h" +#include "V8SVGFontFaceNameElement.h" +#include "V8SVGFontFaceSrcElement.h" +#include "V8SVGFontFaceUriElement.h" +#endif + +#if ENABLE(SVG_FOREIGN_OBJECT) +#include "V8SVGForeignObjectElement.h" +#endif + +#if ENABLE(SVG_USE) +#include "V8SVGUseElement.h" +#endif + +#if ENABLE(SVG) +#include "V8SVGAElement.h" +#include "V8SVGAltGlyphElement.h" +#include "V8SVGCircleElement.h" +#include "V8SVGClipPathElement.h" +#include "V8SVGCursorElement.h" +#include "V8SVGDefsElement.h" +#include "V8SVGDescElement.h" +#include "V8SVGElement.h" +#include "V8SVGEllipseElement.h" +#include "V8SVGException.h" +#include "V8SVGGElement.h" +#include "V8SVGGlyphElement.h" +#include "V8SVGGradientElement.h" +#include "V8SVGImageElement.h" +#include "V8SVGLinearGradientElement.h" +#include "V8SVGLineElement.h" +#include "V8SVGMarkerElement.h" +#include "V8SVGMaskElement.h" +#include "V8SVGMetadataElement.h" +#include "V8SVGPathElement.h" +#include "V8SVGPatternElement.h" +#include "V8SVGPolygonElement.h" +#include "V8SVGPolylineElement.h" +#include "V8SVGRadialGradientElement.h" +#include "V8SVGRectElement.h" +#include "V8SVGScriptElement.h" +#include "V8SVGStopElement.h" +#include "V8SVGStyleElement.h" +#include "V8SVGSVGElement.h" +#include "V8SVGSwitchElement.h" +#include "V8SVGSymbolElement.h" +#include "V8SVGTextContentElement.h" +#include "V8SVGTextElement.h" +#include "V8SVGTextPathElement.h" +#include "V8SVGTextPositioningElement.h" +#include "V8SVGTitleElement.h" +#include "V8SVGTRefElement.h" +#include "V8SVGTSpanElement.h" +#include "V8SVGViewElement.h" +#include "V8SVGAngle.h" +#include "V8SVGAnimatedAngle.h" +#include "V8SVGAnimatedBoolean.h" +#include "V8SVGAnimatedEnumeration.h" +#include "V8SVGAnimatedInteger.h" +#include "V8SVGAnimatedLength.h" +#include "V8SVGAnimatedLengthList.h" +#include "V8SVGAnimatedNumber.h" +#include "V8SVGAnimatedNumberList.h" +#include "V8SVGAnimatedPoints.h" +#include "V8SVGAnimatedPreserveAspectRatio.h" +#include "V8SVGAnimatedRect.h" +#include "V8SVGAnimatedString.h" +#include "V8SVGAnimatedTransformList.h" +#include "V8SVGColor.h" +#include "V8SVGDocument.h" +#include "V8SVGElementInstance.h" +#include "V8SVGElementInstanceList.h" +#include "V8SVGLength.h" +#include "V8SVGLengthList.h" +#include "V8SVGMatrix.h" +#include "V8SVGNumber.h" +#include "V8SVGNumberList.h" +#include "V8SVGPaint.h" +#include "V8SVGPathSeg.h" +#include "V8SVGPathSegArcAbs.h" +#include "V8SVGPathSegArcRel.h" +#include "V8SVGPathSegClosePath.h" +#include "V8SVGPathSegCurvetoCubicAbs.h" +#include "V8SVGPathSegCurvetoCubicRel.h" +#include "V8SVGPathSegCurvetoCubicSmoothAbs.h" +#include "V8SVGPathSegCurvetoCubicSmoothRel.h" +#include "V8SVGPathSegCurvetoQuadraticAbs.h" +#include "V8SVGPathSegCurvetoQuadraticRel.h" +#include "V8SVGPathSegCurvetoQuadraticSmoothAbs.h" +#include "V8SVGPathSegCurvetoQuadraticSmoothRel.h" +#include "V8SVGPathSegLinetoAbs.h" +#include "V8SVGPathSegLinetoHorizontalAbs.h" +#include "V8SVGPathSegLinetoHorizontalRel.h" +#include "V8SVGPathSegLinetoRel.h" +#include "V8SVGPathSegLinetoVerticalAbs.h" +#include "V8SVGPathSegLinetoVerticalRel.h" +#include "V8SVGPathSegList.h" +#include "V8SVGPathSegMovetoAbs.h" +#include "V8SVGPathSegMovetoRel.h" +#include "V8SVGPoint.h" +#include "V8SVGPointList.h" +#include "V8SVGPreserveAspectRatio.h" +#include "V8SVGRect.h" +#include "V8SVGRenderingIntent.h" +#include "V8SVGStringList.h" +#include "V8SVGTransform.h" +#include "V8SVGTransformList.h" +#include "V8SVGUnitTypes.h" +#include "V8SVGURIReference.h" +#include "V8SVGZoomEvent.h" +#endif + +#if ENABLE(VIDEO) +#include "V8HTMLAudioElement.h" +#include "V8HTMLMediaElement.h" +#include "V8HTMLSourceElement.h" +#include "V8HTMLVideoElement.h" +#include "V8MediaError.h" +#include "V8TimeRanges.h" +#endif + +#if ENABLE(WORKERS) +#include "V8AbstractWorker.h" +#include "V8DedicatedWorkerContext.h" +#include "V8Worker.h" +#include "V8WorkerContext.h" +#include "V8WorkerLocation.h" +#include "V8WorkerNavigator.h" +#endif + +#if ENABLE(SHARED_WORKERS) +#include "V8SharedWorker.h" +#endif + +namespace WebCore { + +FunctionTemplateFactory V8ClassIndex::GetFactory(V8WrapperType type) +{ + switch (type) { +#define MAKE_CASE(type, name)\ + case V8ClassIndex::type: return V8##name::GetTemplate; + WRAPPER_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: return NULL; + } +} + + +#define MAKE_CACHE(type, name)\ + static v8::Persistent<v8::FunctionTemplate> name##_cache_; + ALL_WRAPPER_TYPES(MAKE_CACHE) +#undef MAKE_CACHE + + +v8::Persistent<v8::FunctionTemplate>* V8ClassIndex::GetCache(V8WrapperType type) +{ + switch (type) { +#define MAKE_CASE(type, name)\ + case V8ClassIndex::type: return &name##_cache_; + ALL_WRAPPER_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT(false); + return NULL; + } +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Index.h b/WebCore/bindings/v8/V8Index.h index 58af42e..d81537d 100644 --- a/WebCore/bindings/v8/V8Index.h +++ b/WebCore/bindings/v8/V8Index.h @@ -31,8 +31,537 @@ #ifndef V8Index_h #define V8Index_h -// FIXME: This is a temporary forwarding header until all bindings have migrated -// over and v8_index actually becomes V8Index. -#include "v8_index.h" +#include <v8.h> +#include "PlatformString.h" // for WebCore::String + +namespace WebCore { + +typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); + +#if ENABLE(DATAGRID) +#define DATAGRID_HTMLELEMENT_TYPES(V) \ + V(HTMLDATAGRIDCELLELEMENT, HTMLDataGridCellElement) \ + V(HTMLDATAGRIDCOLELEMENT, HTMLDataGridColElement) \ + V(HTMLDATAGRIDELEMENT, HTMLDataGridElement) \ + V(HTMLDATAGRIDROWELEMENT, HTMLDataGridRowElement) +#define DATAGRID_NONNODE_TYPES(V) \ + V(DATAGRIDCOLUMN, DataGridColumn) \ + V(DATAGRIDCOLUMNLIST, DataGridColumnList) +#else +#define DATAGRID_HTMLELEMENT_TYPES(V) +#define DATAGRID_NONNODE_TYPES(V) +#endif + +#if ENABLE(VIDEO) +#define VIDEO_HTMLELEMENT_TYPES(V) \ + V(HTMLAUDIOELEMENT, HTMLAudioElement) \ + V(HTMLMEDIAELEMENT, HTMLMediaElement) \ + V(HTMLSOURCEELEMENT, HTMLSourceElement) \ + V(HTMLVIDEOELEMENT, HTMLVideoElement) +#define VIDEO_NONNODE_TYPES(V) \ + V(MEDIAERROR, MediaError) \ + V(TIMERANGES, TimeRanges) +#else +#define VIDEO_HTMLELEMENT_TYPES(V) +#define VIDEO_NONNODE_TYPES(V) +#endif + +#if ENABLE(WORKERS) +#define WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + V(WORKER, Worker) + +#define WORKER_NONNODE_WRAPPER_TYPES(V) \ + V(ABSTRACTWORKER, AbstractWorker) \ + V(DEDICATEDWORKERCONTEXT, DedicatedWorkerContext) \ + V(WORKERCONTEXT, WorkerContext) \ + V(WORKERLOCATION, WorkerLocation) \ + V(WORKERNAVIGATOR, WorkerNavigator) +#else +#define WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) +#define WORKER_NONNODE_WRAPPER_TYPES(V) +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ + V(DOMAPPLICATIONCACHE, DOMApplicationCache) +#else +#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) +#endif + +#if ENABLE(SHARED_WORKERS) +#define SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + V(SHAREDWORKER, SharedWorker) +#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) +#else +#define SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) +#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) +#endif + +#define DOM_NODE_TYPES(V) \ + V(ATTR, Attr) \ + V(CHARACTERDATA, CharacterData) \ + V(CDATASECTION, CDATASection) \ + V(COMMENT, Comment) \ + V(DOCUMENT, Document) \ + V(DOCUMENTFRAGMENT, DocumentFragment) \ + V(DOCUMENTTYPE, DocumentType) \ + V(ELEMENT, Element) \ + V(ENTITY, Entity) \ + V(ENTITYREFERENCE, EntityReference) \ + V(HTMLDOCUMENT, HTMLDocument) \ + V(NODE, Node) \ + V(NOTATION, Notation) \ + V(PROCESSINGINSTRUCTION, ProcessingInstruction) \ + V(TEXT, Text) \ + V(HTMLANCHORELEMENT, HTMLAnchorElement) \ + V(HTMLAPPLETELEMENT, HTMLAppletElement) \ + V(HTMLAREAELEMENT, HTMLAreaElement) \ + V(HTMLBASEELEMENT, HTMLBaseElement) \ + V(HTMLBASEFONTELEMENT, HTMLBaseFontElement) \ + V(HTMLBLOCKQUOTEELEMENT, HTMLBlockquoteElement) \ + V(HTMLBODYELEMENT, HTMLBodyElement) \ + V(HTMLBRELEMENT, HTMLBRElement) \ + V(HTMLBUTTONELEMENT, HTMLButtonElement) \ + V(HTMLCANVASELEMENT, HTMLCanvasElement) \ + V(HTMLDIRECTORYELEMENT, HTMLDirectoryElement) \ + V(HTMLDIVELEMENT, HTMLDivElement) \ + V(HTMLDLISTELEMENT, HTMLDListElement) \ + V(HTMLEMBEDELEMENT, HTMLEmbedElement) \ + V(HTMLFIELDSETELEMENT, HTMLFieldSetElement) \ + V(HTMLFONTELEMENT, HTMLFontElement) \ + V(HTMLFORMELEMENT, HTMLFormElement) \ + V(HTMLFRAMEELEMENT, HTMLFrameElement) \ + V(HTMLFRAMESETELEMENT, HTMLFrameSetElement) \ + V(HTMLHEADINGELEMENT, HTMLHeadingElement) \ + V(HTMLHEADELEMENT, HTMLHeadElement) \ + V(HTMLHRELEMENT, HTMLHRElement) \ + V(HTMLHTMLELEMENT, HTMLHtmlElement) \ + V(HTMLIFRAMEELEMENT, HTMLIFrameElement) \ + V(HTMLIMAGEELEMENT, HTMLImageElement) \ + V(HTMLINPUTELEMENT, HTMLInputElement) \ + V(HTMLISINDEXELEMENT, HTMLIsIndexElement) \ + V(HTMLLABELELEMENT, HTMLLabelElement) \ + V(HTMLLEGENDELEMENT, HTMLLegendElement) \ + V(HTMLLIELEMENT, HTMLLIElement) \ + V(HTMLLINKELEMENT, HTMLLinkElement) \ + V(HTMLMAPELEMENT, HTMLMapElement) \ + V(HTMLMARQUEEELEMENT, HTMLMarqueeElement) \ + V(HTMLMENUELEMENT, HTMLMenuElement) \ + V(HTMLMETAELEMENT, HTMLMetaElement) \ + V(HTMLMODELEMENT, HTMLModElement) \ + V(HTMLOBJECTELEMENT, HTMLObjectElement) \ + V(HTMLOLISTELEMENT, HTMLOListElement) \ + V(HTMLOPTGROUPELEMENT, HTMLOptGroupElement) \ + V(HTMLOPTIONELEMENT, HTMLOptionElement) \ + V(HTMLPARAGRAPHELEMENT, HTMLParagraphElement) \ + V(HTMLPARAMELEMENT, HTMLParamElement) \ + V(HTMLPREELEMENT, HTMLPreElement) \ + V(HTMLQUOTEELEMENT, HTMLQuoteElement) \ + V(HTMLSCRIPTELEMENT, HTMLScriptElement) \ + V(HTMLSELECTELEMENT, HTMLSelectElement) \ + V(HTMLSTYLEELEMENT, HTMLStyleElement) \ + V(HTMLTABLECAPTIONELEMENT, HTMLTableCaptionElement) \ + V(HTMLTABLECOLELEMENT, HTMLTableColElement) \ + V(HTMLTABLEELEMENT, HTMLTableElement) \ + V(HTMLTABLESECTIONELEMENT, HTMLTableSectionElement) \ + V(HTMLTABLECELLELEMENT, HTMLTableCellElement) \ + V(HTMLTABLEROWELEMENT, HTMLTableRowElement) \ + V(HTMLTEXTAREAELEMENT, HTMLTextAreaElement) \ + V(HTMLTITLEELEMENT, HTMLTitleElement) \ + V(HTMLULISTELEMENT, HTMLUListElement) \ + V(HTMLELEMENT, HTMLElement) \ + DATAGRID_HTMLELEMENT_TYPES(V) \ + VIDEO_HTMLELEMENT_TYPES(V) + +#if ENABLE(SVG_ANIMATION) +#define SVG_ANIMATION_ELEMENT_TYPES(V) \ + V(SVGANIMATECOLORELEMENT, SVGAnimateColorElement) \ + V(SVGANIMATEELEMENT, SVGAnimateElement) \ + V(SVGANIMATETRANSFORMELEMENT, SVGAnimateTransformElement) \ + V(SVGANIMATIONELEMENT, SVGAnimationElement) \ + V(SVGSETELEMENT, SVGSetElement) +#else +#define SVG_ANIMATION_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG_FILTERS) +#define SVG_FILTERS_ELEMENT_TYPES(V) \ + V(SVGCOMPONENTTRANSFERFUNCTIONELEMENT, SVGComponentTransferFunctionElement)\ + V(SVGFEBLENDELEMENT, SVGFEBlendElement) \ + V(SVGFECOLORMATRIXELEMENT, SVGFEColorMatrixElement) \ + V(SVGFECOMPONENTTRANSFERELEMENT, SVGFEComponentTransferElement) \ + V(SVGFECOMPOSITEELEMENT, SVGFECompositeElement) \ + V(SVGFEDIFFUSELIGHTINGELEMENT, SVGFEDiffuseLightingElement) \ + V(SVGFEDISPLACEMENTMAPELEMENT, SVGFEDisplacementMapElement) \ + V(SVGFEDISTANTLIGHTELEMENT, SVGFEDistantLightElement) \ + V(SVGFEFLOODELEMENT, SVGFEFloodElement) \ + V(SVGFEFUNCAELEMENT, SVGFEFuncAElement) \ + V(SVGFEFUNCBELEMENT, SVGFEFuncBElement) \ + V(SVGFEFUNCGELEMENT, SVGFEFuncGElement) \ + V(SVGFEFUNCRELEMENT, SVGFEFuncRElement) \ + V(SVGFEGAUSSIANBLURELEMENT, SVGFEGaussianBlurElement) \ + V(SVGFEIMAGEELEMENT, SVGFEImageElement) \ + V(SVGFEMERGEELEMENT, SVGFEMergeElement) \ + V(SVGFEMERGENODEELEMENT, SVGFEMergeNodeElement) \ + V(SVGFEOFFSETELEMENT, SVGFEOffsetElement) \ + V(SVGFEPOINTLIGHTELEMENT, SVGFEPointLightElement) \ + V(SVGFESPECULARLIGHTINGELEMENT, SVGFESpecularLightingElement) \ + V(SVGFESPOTLIGHTELEMENT, SVGFESpotLightElement) \ + V(SVGFETILEELEMENT, SVGFETileElement) \ + V(SVGFETURBULENCEELEMENT, SVGFETurbulenceElement) \ + V(SVGFILTERELEMENT, SVGFilterElement) +#else +#define SVG_FILTERS_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG_FONTS) +#define SVG_FONTS_ELEMENT_TYPES(V) \ + V(SVGDEFINITIONSRCELEMENT, SVGDefinitionSrcElement) \ + V(SVGFONTFACEELEMENT, SVGFontFaceElement) \ + V(SVGFONTFACEFORMATELEMENT, SVGFontFaceFormatElement) \ + V(SVGFONTFACENAMEELEMENT, SVGFontFaceNameElement) \ + V(SVGFONTFACESRCELEMENT, SVGFontFaceSrcElement) \ + V(SVGFONTFACEURIELEMENT, SVGFontFaceUriElement) +#else +#define SVG_FONTS_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG_FOREIGN_OBJECT) +#define SVG_FOREIGN_OBJECT_ELEMENT_TYPES(V) \ + V(SVGFOREIGNOBJECTELEMENT, SVGForeignObjectElement) +#else +#define SVG_FOREIGN_OBJECT_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG_USE) +#define SVG_USE_ELEMENT_TYPES(V) \ + V(SVGUSEELEMENT, SVGUseElement) +#else +#define SVG_USE_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG) +#define SVG_NODE_TYPES(V) \ + SVG_ANIMATION_ELEMENT_TYPES(V) \ + SVG_FILTERS_ELEMENT_TYPES(V) \ + SVG_FONTS_ELEMENT_TYPES(V) \ + SVG_FOREIGN_OBJECT_ELEMENT_TYPES(V) \ + SVG_USE_ELEMENT_TYPES(V) \ + V(SVGAELEMENT, SVGAElement) \ + V(SVGALTGLYPHELEMENT, SVGAltGlyphElement) \ + V(SVGCIRCLEELEMENT, SVGCircleElement) \ + V(SVGCLIPPATHELEMENT, SVGClipPathElement) \ + V(SVGCURSORELEMENT, SVGCursorElement) \ + V(SVGDEFSELEMENT, SVGDefsElement) \ + V(SVGDESCELEMENT, SVGDescElement) \ + V(SVGELLIPSEELEMENT, SVGEllipseElement) \ + V(SVGGELEMENT, SVGGElement) \ + V(SVGGLYPHELEMENT, SVGGlyphElement) \ + V(SVGGRADIENTELEMENT, SVGGradientElement) \ + V(SVGIMAGEELEMENT, SVGImageElement) \ + V(SVGLINEARGRADIENTELEMENT, SVGLinearGradientElement) \ + V(SVGLINEELEMENT, SVGLineElement) \ + V(SVGMARKERELEMENT, SVGMarkerElement) \ + V(SVGMASKELEMENT, SVGMaskElement) \ + V(SVGMETADATAELEMENT, SVGMetadataElement) \ + V(SVGPATHELEMENT, SVGPathElement) \ + V(SVGPATTERNELEMENT, SVGPatternElement) \ + V(SVGPOLYGONELEMENT, SVGPolygonElement) \ + V(SVGPOLYLINEELEMENT, SVGPolylineElement) \ + V(SVGRADIALGRADIENTELEMENT, SVGRadialGradientElement) \ + V(SVGRECTELEMENT, SVGRectElement) \ + V(SVGSCRIPTELEMENT, SVGScriptElement) \ + V(SVGSTOPELEMENT, SVGStopElement) \ + V(SVGSTYLEELEMENT, SVGStyleElement) \ + V(SVGSVGELEMENT, SVGSVGElement) \ + V(SVGSWITCHELEMENT, SVGSwitchElement) \ + V(SVGSYMBOLELEMENT, SVGSymbolElement) \ + V(SVGTEXTCONTENTELEMENT, SVGTextContentElement) \ + V(SVGTEXTELEMENT, SVGTextElement) \ + V(SVGTEXTPATHELEMENT, SVGTextPathElement) \ + V(SVGTEXTPOSITIONINGELEMENT, SVGTextPositioningElement) \ + V(SVGTITLEELEMENT, SVGTitleElement) \ + V(SVGTREFELEMENT, SVGTRefElement) \ + V(SVGTSPANELEMENT, SVGTSpanElement) \ + V(SVGVIEWELEMENT, SVGViewElement) \ + V(SVGELEMENT, SVGElement) \ + V(SVGDOCUMENT, SVGDocument) +#endif // SVG + + +// ACTIVE_DOM_OBJECT_TYPES are DOM_OBJECT_TYPES that need special treatement +// during GC. +#define ACTIVE_DOM_OBJECT_TYPES(V) \ + V(MESSAGEPORT, MessagePort) \ + V(XMLHTTPREQUEST, XMLHttpRequest) \ + WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) + +// NOTE: DOM_OBJECT_TYPES is split into two halves because +// Visual Studio's Intellinonsense crashes when macros get +// too large. 10-29-08 +// DOM_OBJECT_TYPES are non-node DOM types. +#define DOM_OBJECT_TYPES_1(V) \ + V(BARINFO, BarInfo) \ + V(CANVASGRADIENT, CanvasGradient) \ + V(CANVASPATTERN, CanvasPattern) \ + V(CANVASRENDERINGCONTEXT2D, CanvasRenderingContext2D) \ + V(CLIENTRECT, ClientRect) \ + V(CLIENTRECTLIST, ClientRectList) \ + V(CLIPBOARD, Clipboard) \ + V(CONSOLE, Console) \ + V(COUNTER, Counter) \ + V(CSSCHARSETRULE, CSSCharsetRule) \ + V(CSSFONTFACERULE, CSSFontFaceRule) \ + V(CSSIMPORTRULE, CSSImportRule) \ + V(CSSMEDIARULE, CSSMediaRule) \ + V(CSSPAGERULE, CSSPageRule) \ + V(CSSPRIMITIVEVALUE, CSSPrimitiveValue) \ + V(CSSRULE, CSSRule) \ + V(CSSRULELIST, CSSRuleList) \ + V(CSSSTYLEDECLARATION, CSSStyleDeclaration) \ + V(CSSSTYLERULE, CSSStyleRule) \ + V(CSSSTYLESHEET, CSSStyleSheet) \ + V(CSSVALUE, CSSValue) \ + V(CSSVALUELIST, CSSValueList) \ + V(CSSVARIABLESDECLARATION, CSSVariablesDeclaration) \ + V(CSSVARIABLESRULE, CSSVariablesRule) \ + V(DOMCOREEXCEPTION, DOMCoreException) \ + V(DOMIMPLEMENTATION, DOMImplementation) \ + V(DOMPARSER, DOMParser) \ + V(DOMSELECTION, DOMSelection) \ + V(DOMWINDOW, DOMWindow) \ + V(EVENT, Event) \ + V(EVENTEXCEPTION, EventException) \ + V(FILE, File) \ + V(FILELIST, FileList) \ + V(HISTORY, History) \ + V(HTMLALLCOLLECTION, HTMLAllCollection) \ + V(HTMLCOLLECTION, HTMLCollection) \ + V(HTMLOPTIONSCOLLECTION, HTMLOptionsCollection) \ + V(IMAGEDATA, ImageData) \ + V(CANVASPIXELARRAY, CanvasPixelArray) \ + V(INSPECTORBACKEND, InspectorBackend) \ + V(KEYBOARDEVENT, KeyboardEvent) \ + V(LOCATION, Location) \ + V(MEDIA, Media) \ + V(MEDIALIST, MediaList) + +#define DOM_OBJECT_TYPES_2(V) \ + V(MESSAGECHANNEL, MessageChannel) \ + V(MESSAGEEVENT, MessageEvent) \ + V(MIMETYPE, MimeType) \ + V(MIMETYPEARRAY, MimeTypeArray) \ + V(MOUSEEVENT, MouseEvent) \ + V(MUTATIONEVENT, MutationEvent) \ + V(NAMEDNODEMAP, NamedNodeMap) \ + V(NAVIGATOR, Navigator) \ + V(NODEFILTER, NodeFilter) \ + V(NODEITERATOR, NodeIterator) \ + V(NODELIST, NodeList) \ + V(OVERFLOWEVENT, OverflowEvent) \ + V(PLUGIN, Plugin) \ + V(PLUGINARRAY, PluginArray) \ + V(PROGRESSEVENT, ProgressEvent) \ + V(RANGE, Range) \ + V(RANGEEXCEPTION, RangeException) \ + V(RECT, Rect) \ + V(RGBCOLOR, RGBColor) \ + V(SCREEN, Screen) \ + V(STYLESHEET, StyleSheet) \ + V(STYLESHEETLIST, StyleSheetList) \ + V(TEXTEVENT, TextEvent) \ + V(TEXTMETRICS, TextMetrics) \ + V(TREEWALKER, TreeWalker) \ + V(UIEVENT, UIEvent) \ + V(VALIDITYSTATE, ValidityState) \ + V(WEBKITANIMATIONEVENT, WebKitAnimationEvent) \ + V(WEBKITCSSKEYFRAMERULE, WebKitCSSKeyframeRule) \ + V(WEBKITCSSKEYFRAMESRULE, WebKitCSSKeyframesRule) \ + V(WEBKITCSSMATRIX, WebKitCSSMatrix) \ + V(WEBKITPOINT, WebKitPoint) \ + V(WEBKITCSSTRANSFORMVALUE, WebKitCSSTransformValue) \ + V(WEBKITTRANSITIONEVENT, WebKitTransitionEvent) \ + V(WHEELEVENT, WheelEvent) \ + V(XMLHTTPREQUESTUPLOAD, XMLHttpRequestUpload) \ + V(XMLHTTPREQUESTEXCEPTION, XMLHttpRequestException) \ + V(XMLHTTPREQUESTPROGRESSEVENT, XMLHttpRequestProgressEvent) \ + V(XMLSERIALIZER, XMLSerializer) \ + V(XPATHEVALUATOR, XPathEvaluator) \ + V(XPATHEXCEPTION, XPathException) \ + V(XPATHEXPRESSION, XPathExpression) \ + V(XPATHNSRESOLVER, XPathNSResolver) \ + V(XPATHRESULT, XPathResult) \ + V(XSLTPROCESSOR, XSLTProcessor) \ + ACTIVE_DOM_OBJECT_TYPES(V) \ + APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ + DATAGRID_NONNODE_TYPES(V) \ + VIDEO_NONNODE_TYPES(V) \ + SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) \ + WORKER_NONNODE_WRAPPER_TYPES(V) + +#if ENABLE(DATABASE) +#define DOM_OBJECT_DATABASE_TYPES(V) \ + V(DATABASE, Database) \ + V(SQLERROR, SQLError) \ + V(SQLRESULTSET, SQLResultSet) \ + V(SQLRESULTSETROWLIST, SQLResultSetRowList) \ + V(SQLTRANSACTION, SQLTransaction) +#else +#define DOM_OBJECT_DATABASE_TYPES(V) +#endif + +#if ENABLE(DOM_STORAGE) +#define DOM_OBJECT_STORAGE_TYPES(V) \ + V(STORAGE, Storage) \ + V(STORAGEEVENT, StorageEvent) +#else +#define DOM_OBJECT_STORAGE_TYPES(V) +#endif + +#if ENABLE(WORKERS) +#define DOM_OBJECT_WORKERS_TYPES(V) \ + V(ERROREVENT, ErrorEvent) +#else +#define DOM_OBJECT_WORKERS_TYPES(V) +#endif + +#define DOM_OBJECT_TYPES(V) \ + DOM_OBJECT_TYPES_1(V) \ + DOM_OBJECT_TYPES_2(V) \ + DOM_OBJECT_DATABASE_TYPES(V) \ + DOM_OBJECT_STORAGE_TYPES(V) \ + DOM_OBJECT_WORKERS_TYPES(V) + +#if ENABLE(SVG) +// SVG_OBJECT_TYPES are svg non-node, non-pod types. +#define SVG_OBJECT_TYPES(V) \ + V(SVGANGLE, SVGAngle) \ + V(SVGANIMATEDANGLE, SVGAnimatedAngle) \ + V(SVGANIMATEDBOOLEAN, SVGAnimatedBoolean) \ + V(SVGANIMATEDENUMERATION, SVGAnimatedEnumeration) \ + V(SVGANIMATEDINTEGER, SVGAnimatedInteger) \ + V(SVGANIMATEDLENGTH, SVGAnimatedLength) \ + V(SVGANIMATEDLENGTHLIST, SVGAnimatedLengthList) \ + V(SVGANIMATEDNUMBER, SVGAnimatedNumber) \ + V(SVGANIMATEDNUMBERLIST, SVGAnimatedNumberList) \ + V(SVGANIMATEDPRESERVEASPECTRATIO, SVGAnimatedPreserveAspectRatio) \ + V(SVGANIMATEDRECT, SVGAnimatedRect) \ + V(SVGANIMATEDSTRING, SVGAnimatedString) \ + V(SVGANIMATEDTRANSFORMLIST, SVGAnimatedTransformList) \ + V(SVGCOLOR, SVGColor) \ + V(SVGELEMENTINSTANCE, SVGElementInstance) \ + V(SVGELEMENTINSTANCELIST, SVGElementInstanceList) \ + V(SVGEXCEPTION, SVGException) \ + V(SVGLENGTHLIST, SVGLengthList) \ + V(SVGNUMBERLIST, SVGNumberList) \ + V(SVGPAINT, SVGPaint) \ + V(SVGPATHSEG, SVGPathSeg) \ + V(SVGPATHSEGARCABS, SVGPathSegArcAbs) \ + V(SVGPATHSEGARCREL, SVGPathSegArcRel) \ + V(SVGPATHSEGCLOSEPATH, SVGPathSegClosePath) \ + V(SVGPATHSEGCURVETOCUBICABS, SVGPathSegCurvetoCubicAbs) \ + V(SVGPATHSEGCURVETOCUBICREL, SVGPathSegCurvetoCubicRel) \ + V(SVGPATHSEGCURVETOCUBICSMOOTHABS, SVGPathSegCurvetoCubicSmoothAbs) \ + V(SVGPATHSEGCURVETOCUBICSMOOTHREL, SVGPathSegCurvetoCubicSmoothRel) \ + V(SVGPATHSEGCURVETOQUADRATICABS, SVGPathSegCurvetoQuadraticAbs) \ + V(SVGPATHSEGCURVETOQUADRATICREL, SVGPathSegCurvetoQuadraticRel) \ + V(SVGPATHSEGCURVETOQUADRATICSMOOTHABS, SVGPathSegCurvetoQuadraticSmoothAbs)\ + V(SVGPATHSEGCURVETOQUADRATICSMOOTHREL, SVGPathSegCurvetoQuadraticSmoothRel)\ + V(SVGPATHSEGLINETOABS, SVGPathSegLinetoAbs) \ + V(SVGPATHSEGLINETOHORIZONTALABS, SVGPathSegLinetoHorizontalAbs) \ + V(SVGPATHSEGLINETOHORIZONTALREL, SVGPathSegLinetoHorizontalRel) \ + V(SVGPATHSEGLINETOREL, SVGPathSegLinetoRel) \ + V(SVGPATHSEGLINETOVERTICALABS, SVGPathSegLinetoVerticalAbs) \ + V(SVGPATHSEGLINETOVERTICALREL, SVGPathSegLinetoVerticalRel) \ + V(SVGPATHSEGLIST, SVGPathSegList) \ + V(SVGPATHSEGMOVETOABS, SVGPathSegMovetoAbs) \ + V(SVGPATHSEGMOVETOREL, SVGPathSegMovetoRel) \ + V(SVGPOINTLIST, SVGPointList) \ + V(SVGPRESERVEASPECTRATIO, SVGPreserveAspectRatio) \ + V(SVGRENDERINGINTENT, SVGRenderingIntent) \ + V(SVGSTRINGLIST, SVGStringList) \ + V(SVGTRANSFORMLIST, SVGTransformList) \ + V(SVGUNITTYPES, SVGUnitTypes) \ + V(SVGZOOMEVENT, SVGZoomEvent) + +// SVG POD types should list all types whose IDL has PODType declaration. +#define SVG_POD_TYPES(V) \ + V(SVGLENGTH, SVGLength) \ + V(SVGTRANSFORM, SVGTransform) \ + V(SVGMATRIX, SVGMatrix) \ + V(SVGNUMBER, SVGNumber) \ + V(SVGPOINT, SVGPoint) \ + V(SVGRECT, SVGRect) + +// POD types can have different implementation names, see CodeGenerateV8.pm. +#define SVG_POD_NATIVE_TYPES(V) \ + V(SVGLENGTH, SVGLength) \ + V(SVGTRANSFORM, SVGTransform) \ + V(SVGMATRIX, TransformationMatrix) \ + V(SVGNUMBER, float) \ + V(SVGPOINT, FloatPoint) \ + V(SVGRECT, FloatRect) + +// Shouldn't generate code for these two types. +#define SVG_NO_WRAPPER_TYPES(V) \ + V(SVGURIREFERENCE, SVGURIReference) \ + V(SVGANIMATEDPOINTS, SVGAnimatedPoints) + +// SVG_NONNODE_TYPES are SVG non-node object types, pod typs and +// numerical types. +#define SVG_NONNODE_TYPES(V) \ + SVG_OBJECT_TYPES(V) \ + SVG_POD_TYPES(V) +#endif // SVG + +// EVENTTARGET, EVENTLISTENER, and NPOBJECT do not have V8 wrappers. +#define DOM_NO_WRAPPER_TYPES(V) \ + V(EVENTTARGET, EventTarget) \ + V(EVENTLISTENER, EventListener) \ + V(NPOBJECT, NPObject) + +#if ENABLE(SVG) +#define WRAPPER_TYPES(V) DOM_NODE_TYPES(V) DOM_OBJECT_TYPES(V) SVG_NODE_TYPES(V) SVG_NONNODE_TYPES(V) +#define NO_WRAPPER_TYPES(V) DOM_NO_WRAPPER_TYPES(V) SVG_NO_WRAPPER_TYPES(V) +#else // SVG +#define WRAPPER_TYPES(V) DOM_NODE_TYPES(V) DOM_OBJECT_TYPES(V) +#define NO_WRAPPER_TYPES(V) DOM_NO_WRAPPER_TYPES(V) +#endif // SVG + +#define ALL_WRAPPER_TYPES(V) WRAPPER_TYPES(V) NO_WRAPPER_TYPES(V) + + class V8ClassIndex { + public: + // Type must start at non-negative numbers. See ToInt, FromInt. + enum V8WrapperType { + INVALID_CLASS_INDEX = 0, + +#define DEFINE_ENUM(name, type) name, + ALL_WRAPPER_TYPES(DEFINE_ENUM) +#undef DEFINE_ENUM + + CLASSINDEX_END, + WRAPPER_TYPE_COUNT = CLASSINDEX_END + }; + + // FIXME: Convert to toInt after all the bindings are in one place. + static int ToInt(V8WrapperType type) { return static_cast<int>(type); } + + // FIXME: Convert to fromInt after all the bindings are in one place. + static V8WrapperType FromInt(int v) { + ASSERT(INVALID_CLASS_INDEX <= v && v < CLASSINDEX_END); + return static_cast<V8WrapperType>(v); + } + + // FIXME: Convert to getFactory after all the bindings are in one place. + static FunctionTemplateFactory GetFactory(V8WrapperType type); + + // Returns a field to be used as cache for the template for the given type + // FIXME: Convert to getCache after all the bindings are in one place. + static v8::Persistent<v8::FunctionTemplate>* GetCache(V8WrapperType type); + }; + +} #endif // V8Index_h diff --git a/WebCore/bindings/v8/V8IsolatedWorld.cpp b/WebCore/bindings/v8/V8IsolatedWorld.cpp new file mode 100644 index 0000000..1457545 --- /dev/null +++ b/WebCore/bindings/v8/V8IsolatedWorld.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "V8IsolatedWorld.h" + +#include <v8.h> + +#include "Frame.h" +#include "FrameLoaderClient.h" +#include "HashMap.h" +#include "ScriptController.h" +#include "V8DOMWindow.h" +#include "V8HiddenPropertyName.h" + +namespace WebCore { + +static int isolatedWorldCount = 0; + +static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world) +{ + // Our context is going away. Time to clean up the world. + V8IsolatedWorld* world = static_cast<V8IsolatedWorld*>(isolated_world); + delete world; +} + +void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup) +{ + v8::HandleScope scope; + v8::Persistent<v8::Context> context = proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup); + + // Run code in the new context. + v8::Context::Scope context_scope(context); + + // The lifetime of this object is controlled by the V8 GC. + // We need to create the world before touching DOM wrappers. + V8IsolatedWorld* world = new V8IsolatedWorld(context); + + V8Proxy::installHiddenObjectPrototype(context); + proxy->installDOMWindow(context, proxy->frame()->domWindow()); + + proxy->frame()->loader()->client()->didCreateIsolatedScriptContext(); + + for (size_t i = 0; i < sources.size(); ++i) + proxy->evaluate(sources[i], 0); + + // Using the default security token means that the canAccess is always + // called, which is slow. + // FIXME: Use tokens where possible. This will mean keeping track of all + // created contexts so that they can all be updated when the + // document domain + // changes. + // FIXME: Move this statement above proxy->evaluate? It seems like we + // should set up the token before running the script. + context->UseDefaultSecurityToken(); + + context.Dispose(); + // WARNING! This might well delete |world|. +} + +V8IsolatedWorld::V8IsolatedWorld(v8::Handle<v8::Context> context) + : m_context(v8::Persistent<v8::Context>::New(context)) +{ + ++isolatedWorldCount; + m_context.MakeWeak(this, &contextWeakReferenceCallback); + m_context->Global()->SetHiddenValue(V8HiddenPropertyName::isolatedWorld(), v8::External::Wrap(this)); +} + +V8IsolatedWorld::~V8IsolatedWorld() +{ + --isolatedWorldCount; + m_context.Dispose(); + m_context.Clear(); +} + +V8IsolatedWorld* V8IsolatedWorld::getEntered() +{ + if (isolatedWorldCount == 0) { + // This is a temporary performance optimization. Essentially, + // GetHiddenValue is too slow for this code path. We need to get the + // V8 team to add a real property to v8::Context for isolated worlds. + // Until then, we optimize the common case of not having any isolated + // worlds at all. + return 0; + } + + if (!v8::Context::InContext()) + return 0; + v8::HandleScope scope; + + v8::Local<v8::Value> world = v8::Context::GetEntered()->Global()->GetHiddenValue(V8HiddenPropertyName::isolatedWorld()); + if (world.IsEmpty()) + return 0; + + return static_cast<V8IsolatedWorld*>(v8::External::Unwrap(world)); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8IsolatedWorld.h b/WebCore/bindings/v8/V8IsolatedWorld.h new file mode 100644 index 0000000..2036e65 --- /dev/null +++ b/WebCore/bindings/v8/V8IsolatedWorld.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8IsolatedWorld_h +#define V8IsolatedWorld_h + +#include <v8.h> + +#include "V8DOMMap.h" +#include "V8Index.h" +#include "V8Utilities.h" +#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode + +namespace WebCore { + + class V8Proxy; + + // V8IsolatedWorld + // + // V8IsolatedWorld represents a isolated execution environment for + // JavaScript. Each isolated world executes in parallel with the main + // JavaScript world. An isolated world has access to the same DOM data + // structures as the main world but none of the JavaScript pointers. + // + // It is an error to ever share a JavaScript pointer between two isolated + // worlds or between an isolated world and the main world. Because + // isolated worlds have access to the DOM, they need their own DOM wrappers + // to avoid having pointers to the main world's DOM wrappers (which are + // JavaScript objects). + // + class V8IsolatedWorld { + public: + ~V8IsolatedWorld(); + + // Evaluate JavaScript in a new isolated world. The script has access + // to the DOM of the document associated with |proxy|. + static void evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup); + + // Returns the isolated world associated with + // v8::Context::GetEntered(). Because worlds are isolated, the entire + // JavaScript call stack should be from the same isolated world. + // Returns NULL if the entered context is from the main world. + // + // FIXME: Consider edge cases with DOM mutation events that might + // violate this invariant. + // + static V8IsolatedWorld* getEntered(); + + v8::Handle<v8::Context> context() { return m_context; } + + DOMDataStore* getDOMDataStore() const { return m_domDataStore.getStore(); } + + private: + // The lifetime of an isolated world is managed by the V8 garbage + // collector. In particular, the object created by this constructor is + // freed when |context| is garbage collected. + explicit V8IsolatedWorld(v8::Handle<v8::Context> context); + + // The v8::Context for the isolated world. This object is keep on the + // heap as long as |m_context| has not been garbage collected. + v8::Persistent<v8::Context> m_context; + + // The backing store for the isolated world's DOM wrappers. This class + // doesn't have visibility into the wrappers. This handle simply helps + // manage their lifetime. + DOMDataStoreHandle m_domDataStore; + }; + +} // namespace WebCore + +#endif // V8IsolatedWorld_h diff --git a/WebCore/bindings/v8/V8LazyEventListener.cpp b/WebCore/bindings/v8/V8LazyEventListener.cpp index f0e81de..59fa7be 100644 --- a/WebCore/bindings/v8/V8LazyEventListener.cpp +++ b/WebCore/bindings/v8/V8LazyEventListener.cpp @@ -54,7 +54,7 @@ V8LazyEventListener::~V8LazyEventListener() // Dispose wrapped function if (!m_wrappedFunction.IsEmpty()) { #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_wrappedFunction); + V8GCController::unregisterGlobalHandle(this, m_wrappedFunction); #endif m_wrappedFunction.Dispose(); m_wrappedFunction.Clear(); @@ -77,12 +77,12 @@ v8::Local<v8::Function> V8LazyEventListener::getListenerFunction() v8::HandleScope handleScope; // Use the outer scope to hold context. - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); // Bail out if we could not get the context. - if (context.IsEmpty()) + if (v8Context.IsEmpty()) return v8::Local<v8::Function>(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); // Wrap function around the event code. The parenthesis around the function are needed so that evaluating the code yields // the function value. Without the parenthesis the function value is thrown away. @@ -102,19 +102,19 @@ v8::Local<v8::Function> V8LazyEventListener::getListenerFunction() code.append("\n})"); v8::Handle<v8::String> codeExternalString = v8ExternalString(code); - v8::Handle<v8::Script> script = V8Proxy::CompileScript(codeExternalString, m_frame->document()->url(), m_lineNumber - 1); + v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_frame->document()->url(), m_lineNumber - 1); if (!script.IsEmpty()) { V8Proxy* proxy = V8Proxy::retrieve(m_frame); ASSERT(proxy); - v8::Local<v8::Value> value = proxy->RunScript(script, false); + v8::Local<v8::Value> value = proxy->runScript(script, false); if (!value.IsEmpty()) { ASSERT(value->IsFunction()); v8::Local<v8::Function> listenerFunction = v8::Local<v8::Function>::Cast(value); - listenerFunction->SetName(v8::String::New(FromWebCoreString(m_functionName), m_functionName.length())); + listenerFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); m_listener = v8::Persistent<v8::Function>::New(listenerFunction); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(EVENT_LISTENER, this, m_listener); + V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener); #endif } } @@ -134,7 +134,7 @@ v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(v8::Handle<v8::Va v8::Handle<v8::Value> parameters[1] = { jsEvent }; V8Proxy* proxy = V8Proxy::retrieve(m_frame); - return proxy->CallFunction(handlerFunction, receiver, 1, parameters); + return proxy->callFunction(handlerFunction, receiver, 1, parameters); } @@ -158,12 +158,12 @@ v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction() v8::HandleScope handleScope; // Use the outer scope to hold context. - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); // Bail out if we cannot get the context. - if (context.IsEmpty()) + if (v8Context.IsEmpty()) return v8::Local<v8::Function>(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); // FIXME: cache the wrapper function. @@ -184,11 +184,11 @@ v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction() // Insert '\n' otherwise //-style comments could break the handler. code.append( "\n}).call(this, evt);}}}})"); v8::Handle<v8::String> codeExternalString = v8ExternalString(code); - v8::Handle<v8::Script> script = V8Proxy::CompileScript(codeExternalString, m_frame->document()->url(), m_lineNumber); + v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_frame->document()->url(), m_lineNumber); if (!script.IsEmpty()) { V8Proxy* proxy = V8Proxy::retrieve(m_frame); ASSERT(proxy); - v8::Local<v8::Value> value = proxy->RunScript(script, false); + v8::Local<v8::Value> value = proxy->runScript(script, false); if (!value.IsEmpty()) { ASSERT(value->IsFunction()); @@ -218,7 +218,7 @@ v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction() } #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(EVENT_LISTENER, this, m_wrappedFunction); + V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_wrappedFunction); #endif m_wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); } diff --git a/WebCore/bindings/v8/V8NPObject.cpp b/WebCore/bindings/v8/V8NPObject.cpp new file mode 100644 index 0000000..b6bf0f7 --- /dev/null +++ b/WebCore/bindings/v8/V8NPObject.cpp @@ -0,0 +1,351 @@ +/* +* Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Google Inc. nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "config.h" + +#include "V8NPObject.h" + +#include "HTMLPlugInElement.h" +#include "NPV8Object.h" +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8HTMLAppletElement.h" +#include "V8HTMLEmbedElement.h" +#include "V8HTMLObjectElement.h" +#include "V8Helpers.h" +#include "V8NPUtils.h" +#include "V8Proxy.h" +#include "npruntime_impl.h" +#include "npruntime_priv.h" +#include "wtf/OwnArrayPtr.h" + +using namespace WebCore; + +enum InvokeFunctionType { + InvokeMethod = 1, + InvokeConstruct = 2, + InvokeDefault = 3 +}; + +// FIXME: need comments. +// Params: holder could be HTMLEmbedElement or NPObject +static v8::Handle<v8::Value> npObjectInvokeImpl(const v8::Arguments& args, InvokeFunctionType functionId) +{ + NPObject* npObject; + + // These three types are subtypes of HTMLPlugInElement. + if (V8HTMLAppletElement::HasInstance(args.Holder()) || V8HTMLEmbedElement::HasInstance(args.Holder()) + || V8HTMLObjectElement::HasInstance(args.Holder())) { + // The holder object is a subtype of HTMLPlugInElement. + HTMLPlugInElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(args.Holder()); + ScriptInstance scriptInstance = element->getInstance(); + if (scriptInstance) + npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, scriptInstance->instance()); + else + npObject = 0; + } else { + // The holder object is not a subtype of HTMLPlugInElement, it must be an NPObject which has three + // internal fields. + if (args.Holder()->InternalFieldCount() != V8Custom::kNPObjectInternalFieldCount) + return throwError("NPMethod called on non-NPObject", V8Proxy::ReferenceError); + + npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, args.Holder()); + } + + // Verify that our wrapper wasn't using a NPObject which has already been deleted. + if (!npObject || !_NPN_IsAlive(npObject)) + return throwError("NPObject deleted", V8Proxy::ReferenceError); + + // Wrap up parameters. + int numArgs = args.Length(); + OwnArrayPtr<NPVariant> npArgs(new NPVariant[numArgs]); + + for (int i = 0; i < numArgs; i++) + convertV8ObjectToNPVariant(args[i], npObject, &npArgs[i]); + + NPVariant result; + VOID_TO_NPVARIANT(result); + + switch (functionId) { + case InvokeMethod: + if (npObject->_class->invoke) { + v8::Handle<v8::String> functionName(v8::String::Cast(*args.Data())); + NPIdentifier identifier = getStringIdentifier(functionName); + npObject->_class->invoke(npObject, identifier, npArgs.get(), numArgs, &result); + } + break; + case InvokeConstruct: + if (npObject->_class->construct) + npObject->_class->construct(npObject, npArgs.get(), numArgs, &result); + break; + case InvokeDefault: + if (npObject->_class->invokeDefault) + npObject->_class->invokeDefault(npObject, npArgs.get(), numArgs, &result); + break; + default: + break; + } + + for (int i=0; i < numArgs; i++) + _NPN_ReleaseVariantValue(&npArgs[i]); + + // Unwrap return values. + v8::Handle<v8::Value> returnValue = convertNPVariantToV8Object(&result, npObject); + _NPN_ReleaseVariantValue(&result); + + return returnValue; +} + + +v8::Handle<v8::Value> npObjectMethodHandler(const v8::Arguments& args) +{ + return npObjectInvokeImpl(args, InvokeMethod); +} + + +v8::Handle<v8::Value> npObjectInvokeDefaultHandler(const v8::Arguments& args) +{ + if (args.IsConstructCall()) + return npObjectInvokeImpl(args, InvokeConstruct); + else + return npObjectInvokeImpl(args, InvokeDefault); +} + + +static void weakTemplateCallback(v8::Persistent<v8::Value>, void* parameter); + +// NPIdentifier is PrivateIdentifier*. +static WeakReferenceMap<PrivateIdentifier, v8::FunctionTemplate> staticTemplateMap(&weakTemplateCallback); + +static void weakTemplateCallback(v8::Persistent<v8::Value> object, void* parameter) +{ + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(parameter); + ASSERT(identifier); + ASSERT(staticTemplateMap.contains(identifier)); + + staticTemplateMap.forget(identifier); +} + + +static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> key) +{ + NPObject* npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); + + // Verify that our wrapper wasn't using a NPObject which + // has already been deleted. + if (!npObject || !_NPN_IsAlive(npObject)) + return throwError("NPObject deleted", V8Proxy::ReferenceError); + + + if (npObject->_class->hasProperty && npObject->_class->hasProperty(npObject, identifier) + && npObject->_class->getProperty) { + + NPVariant result; + VOID_TO_NPVARIANT(result); + if (!npObject->_class->getProperty(npObject, identifier, &result)) + return v8::Handle<v8::Value>(); + + v8::Handle<v8::Value> returnValue = convertNPVariantToV8Object(&result, npObject); + _NPN_ReleaseVariantValue(&result); + return returnValue; + + } else if (key->IsString() && npObject->_class->hasMethod && npObject->_class->hasMethod(npObject, identifier)) { + PrivateIdentifier* id = static_cast<PrivateIdentifier*>(identifier); + v8::Persistent<v8::FunctionTemplate> functionTemplate = staticTemplateMap.get(id); + // Cache templates using identifier as the key. + if (functionTemplate.IsEmpty()) { + // Create a new template. + v8::Local<v8::FunctionTemplate> temp = v8::FunctionTemplate::New(); + temp->SetCallHandler(npObjectMethodHandler, key); + functionTemplate = v8::Persistent<v8::FunctionTemplate>::New(temp); + staticTemplateMap.set(id, functionTemplate); + } + + // FunctionTemplate caches function for each context. + v8::Local<v8::Function> v8Function = functionTemplate->GetFunction(); + v8Function->SetName(v8::Handle<v8::String>::Cast(key)); + return v8Function; + } + + return v8::Handle<v8::Value>(); +} + +v8::Handle<v8::Value> npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + NPIdentifier identifier = getStringIdentifier(name); + return npObjectGetProperty(info.Holder(), identifier, name); +} + +v8::Handle<v8::Value> npObjectIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) +{ + NPIdentifier identifier = _NPN_GetIntIdentifier(index); + return npObjectGetProperty(info.Holder(), identifier, v8::Number::New(index)); +} + +v8::Handle<v8::Value> npObjectGetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name) +{ + NPIdentifier identifier = getStringIdentifier(name); + return npObjectGetProperty(self, identifier, name); +} + +v8::Handle<v8::Value> npObjectGetIndexedProperty(v8::Local<v8::Object> self, uint32_t index) +{ + NPIdentifier identifier = _NPN_GetIntIdentifier(index); + return npObjectGetProperty(self, identifier, v8::Number::New(index)); +} + +static v8::Handle<v8::Value> npObjectSetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> value) +{ + NPObject* npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); + + // Verify that our wrapper wasn't using a NPObject which has already been deleted. + if (!npObject || !_NPN_IsAlive(npObject)) { + throwError("NPObject deleted", V8Proxy::ReferenceError); + return value; // Intercepted, but an exception was thrown. + } + + if (npObject->_class->hasProperty && npObject->_class->hasProperty(npObject, identifier) + && npObject->_class->setProperty) { + + NPVariant npValue; + VOID_TO_NPVARIANT(npValue); + convertV8ObjectToNPVariant(value, npObject, &npValue); + bool success = npObject->_class->setProperty(npObject, identifier, &npValue); + _NPN_ReleaseVariantValue(&npValue); + if (success) + return value; // Intercept the call. + } + return notHandledByInterceptor(); +} + + +v8::Handle<v8::Value> npObjectNamedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + NPIdentifier identifier = getStringIdentifier(name); + return npObjectSetProperty(info.Holder(), identifier, value); +} + + +v8::Handle<v8::Value> npObjectIndexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + NPIdentifier identifier = _NPN_GetIntIdentifier(index); + return npObjectSetProperty(info.Holder(), identifier, value); +} + +v8::Handle<v8::Value> npObjectSetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value> value) +{ + NPIdentifier identifier = getStringIdentifier(name); + return npObjectSetProperty(self, identifier, value); +} + +v8::Handle<v8::Value> npObjectSetIndexedProperty(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value> value) +{ + NPIdentifier identifier = _NPN_GetIntIdentifier(index); + return npObjectSetProperty(self, identifier, value); +} + + +static void weakNPObjectCallback(v8::Persistent<v8::Value>, void* parameter); + +static DOMWrapperMap<NPObject> staticNPObjectMap(&weakNPObjectCallback); + +static void weakNPObjectCallback(v8::Persistent<v8::Value> object, void* parameter) +{ + NPObject* npObject = static_cast<NPObject*>(parameter); + ASSERT(staticNPObjectMap.contains(npObject)); + ASSERT(npObject); + + // Must remove from our map before calling _NPN_ReleaseObject(). _NPN_ReleaseObject can call ForgetV8ObjectForNPObject, which + // uses the table as well. + staticNPObjectMap.forget(npObject); + + if (_NPN_IsAlive(npObject)) + _NPN_ReleaseObject(npObject); +} + + +v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root) +{ + static v8::Persistent<v8::FunctionTemplate> npObjectDesc; + + ASSERT(v8::Context::InContext()); + + // If this is a v8 object, just return it. + if (object->_class == npScriptObjectClass) { + V8NPObject* v8NPObject = reinterpret_cast<V8NPObject*>(object); + return v8::Local<v8::Object>::New(v8NPObject->v8Object); + } + + // If we've already wrapped this object, just return it. + if (staticNPObjectMap.contains(object)) + return v8::Local<v8::Object>::New(staticNPObjectMap.get(object)); + + // FIXME: we should create a Wrapper type as a subclass of JSObject. It has two internal fields, field 0 is the wrapped + // pointer, and field 1 is the type. There should be an api function that returns unused type id. The same Wrapper type + // can be used by DOM bindings. + if (npObjectDesc.IsEmpty()) { + npObjectDesc = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); + npObjectDesc->InstanceTemplate()->SetInternalFieldCount(V8Custom::kNPObjectInternalFieldCount); + npObjectDesc->InstanceTemplate()->SetNamedPropertyHandler(npObjectNamedPropertyGetter, npObjectNamedPropertySetter); + npObjectDesc->InstanceTemplate()->SetIndexedPropertyHandler(npObjectIndexedPropertyGetter, npObjectIndexedPropertySetter); + npObjectDesc->InstanceTemplate()->SetCallAsFunctionHandler(npObjectInvokeDefaultHandler); + } + + v8::Handle<v8::Function> v8Function = npObjectDesc->GetFunction(); + v8::Local<v8::Object> value = SafeAllocation::newInstance(v8Function); + + // If we were unable to allocate the instance, we avoid wrapping and registering the NP object. + if (value.IsEmpty()) + return value; + + wrapNPObject(value, object); + + // KJS retains the object as part of its wrapper (see Bindings::CInstance). + _NPN_RetainObject(object); + + _NPN_RegisterObject(object, root); + + // Maintain a weak pointer for v8 so we can cleanup the object. + v8::Persistent<v8::Object> weakRef = v8::Persistent<v8::Object>::New(value); + staticNPObjectMap.set(object, weakRef); + + return value; +} + +void forgetV8ObjectForNPObject(NPObject* object) +{ + if (staticNPObjectMap.contains(object)) { + v8::HandleScope scope; + v8::Persistent<v8::Object> handle(staticNPObjectMap.get(object)); + V8DOMWrapper::setDOMWrapper(handle, WebCore::V8ClassIndex::NPOBJECT, 0); + staticNPObjectMap.forget(object); + _NPN_ReleaseObject(object); + } +} diff --git a/WebCore/bindings/v8/V8NPObject.h b/WebCore/bindings/v8/V8NPObject.h new file mode 100644 index 0000000..0a759b5 --- /dev/null +++ b/WebCore/bindings/v8/V8NPObject.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8NPObject_h +#define V8NPObject_h + +#include <v8.h> +#include "third_party/npapi/bindings/npruntime.h" + +// These functions can be replaced by normal JS operation. +// Getters +v8::Handle<v8::Value> npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectGetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name); +v8::Handle<v8::Value> npObjectGetIndexedProperty(v8::Local<v8::Object> self, uint32_t index); + +// Setters +v8::Handle<v8::Value> npObjectNamedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectIndexedPropertySetter(uint32_t index, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectSetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value>); +v8::Handle<v8::Value> npObjectSetIndexedProperty(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value>); + +v8::Handle<v8::Value> npObjectInvokeDefaultHandler(const v8::Arguments&); + +// Get a wrapper for a NPObject. +// If the object is already wrapped, the pre-existing wrapper will be returned. If the object is not wrapped, wrap it, and +// give V8 a weak reference to the wrapper which will cleanup when there are no more JS references to the object. +v8::Local<v8::Object> createV8ObjectForNPObject(NPObject*, NPObject* root); + +// Tell V8 to forcibly remove an object. +// This is used at plugin teardown so that the caller can aggressively unload the plugin library. After calling this +// function, the persistent handle to the wrapper will be gone, and the wrapped NPObject will be removed so that it +// cannot be referred to. +void forgetV8ObjectForNPObject(NPObject*); + +#endif // V8NPObject_h diff --git a/WebCore/bindings/v8/V8NPUtils.cpp b/WebCore/bindings/v8/V8NPUtils.cpp new file mode 100644 index 0000000..17855d7 --- /dev/null +++ b/WebCore/bindings/v8/V8NPUtils.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "V8NPUtils.h" + +#include "DOMWindow.h" +#include "Frame.h" +#include "PlatformString.h" +#undef LOG + +#include "NPV8Object.h" +#include "V8NPObject.h" +#include "V8Proxy.h" +#include "npruntime_impl.h" +#include "npruntime_priv.h" + +void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NPVariant* result) +{ + VOID_TO_NPVARIANT(*result); + + // It is really the caller's responsibility to deal with the empty handle case because there could be different actions to + // take in different contexts. + ASSERT(!object.IsEmpty()); + + if (object.IsEmpty()) + return; + + if (object->IsInt32()) + INT32_TO_NPVARIANT(object->NumberValue(), *result); + else if (object->IsNumber()) + DOUBLE_TO_NPVARIANT(object->NumberValue(), *result); + else if (object->IsBoolean()) + BOOLEAN_TO_NPVARIANT(object->BooleanValue(), *result); + else if (object->IsNull()) + NULL_TO_NPVARIANT(*result); + else if (object->IsUndefined()) + VOID_TO_NPVARIANT(*result); + else if (object->IsString()) { + v8::String::Utf8Value utf8(object); + char* utf8_chars = strdup(*utf8); + STRINGN_TO_NPVARIANT(utf8_chars, utf8.length(), *result); + } else if (object->IsObject()) { + WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(WebCore::V8Proxy::currentContext()); + NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window); + if (npobject) + _NPN_RegisterObject(npobject, owner); + OBJECT_TO_NPVARIANT(npobject, *result); + } +} + + +v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObject* npobject) +{ + NPVariantType type = variant->type; + + switch (type) { + case NPVariantType_Int32: + return v8::Integer::New(NPVARIANT_TO_INT32(*variant)); + case NPVariantType_Double: + return v8::Number::New(NPVARIANT_TO_DOUBLE(*variant)); + case NPVariantType_Bool: + return NPVARIANT_TO_BOOLEAN(*variant) ? v8::True() : v8::False(); + case NPVariantType_Null: + return v8::Null(); + case NPVariantType_Void: + return v8::Undefined(); + case NPVariantType_String: { + NPString src = NPVARIANT_TO_STRING(*variant); + return v8::String::New(src.UTF8Characters, src.UTF8Length); + } + case NPVariantType_Object: { + NPObject* obj = NPVARIANT_TO_OBJECT(*variant); + if (obj->_class == npScriptObjectClass) + return reinterpret_cast<V8NPObject*>(obj)->v8Object; + return createV8ObjectForNPObject(obj, npobject); + } + default: + return v8::Undefined(); + } +} + +// Helper function to create an NPN String Identifier from a v8 string. +NPIdentifier getStringIdentifier(v8::Handle<v8::String> str) +{ + const int kStackBufferSize = 100; + + int bufferLength = str->Utf8Length() + 1; + if (bufferLength <= kStackBufferSize) { + // Use local stack buffer to avoid heap allocations for small strings. Here we should only use the stack space for + // stackBuffer when it's used, not when we use the heap. + // + // WriteUtf8 is guaranteed to generate a null-terminated string because bufferLength is constructed to be one greater + // than the string length. + char stackBuffer[kStackBufferSize]; + str->WriteUtf8(stackBuffer, bufferLength); + return _NPN_GetStringIdentifier(stackBuffer); + } + + v8::String::Utf8Value utf8(str); + return _NPN_GetStringIdentifier(*utf8); +} diff --git a/WebCore/bindings/v8/V8NPUtils.h b/WebCore/bindings/v8/V8NPUtils.h new file mode 100644 index 0000000..82a74b3 --- /dev/null +++ b/WebCore/bindings/v8/V8NPUtils.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8NPUtils_h +#define V8NPUtils_h + +#include <v8.h> +#include "third_party/npapi/bindings/npruntime.h" + +// Convert a V8 Value of any type (string, bool, object, etc) to a NPVariant. +void convertV8ObjectToNPVariant(v8::Local<v8::Value>, NPObject*, NPVariant*); + +// Convert a NPVariant (string, bool, object, etc) back to a V8 Value. The owner object is the NPObject which relates to the +// object, if the object is an Object. The created NPObject will be tied to the lifetime of the owner. +v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant*, NPObject*); + +// Helper function to create an NPN String Identifier from a v8 string. +NPIdentifier getStringIdentifier(v8::Handle<v8::String>); + +#endif // V8NPUtils_h diff --git a/WebCore/bindings/v8/V8NodeFilterCondition.cpp b/WebCore/bindings/v8/V8NodeFilterCondition.cpp index b5ae30c..9f57a44 100644 --- a/WebCore/bindings/v8/V8NodeFilterCondition.cpp +++ b/WebCore/bindings/v8/V8NodeFilterCondition.cpp @@ -44,14 +44,14 @@ V8NodeFilterCondition::V8NodeFilterCondition(v8::Handle<v8::Value> filter) : m_filter(v8::Persistent<v8::Value>::New(filter)) { #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(NODE_FILTER, this, m_filter); + V8GCController::registerGlobalHandle(NODE_FILTER, this, m_filter); #endif } V8NodeFilterCondition::~V8NodeFilterCondition() { #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_filter); + V8GCController::unregisterGlobalHandle(this, m_filter); #endif m_filter.Dispose(); m_filter.Clear(); @@ -69,12 +69,12 @@ short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const v8::Handle<v8::Object> object = v8::Context::GetCurrent()->Global(); v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(m_filter); OwnArrayPtr<v8::Handle<v8::Value> > args(new v8::Handle<v8::Value>[1]); - args[0] = V8Proxy::ToV8Object(V8ClassIndex::NODE, node); + args[0] = V8DOMWrapper::convertToV8Object(V8ClassIndex::NODE, node); V8Proxy* proxy = V8Proxy::retrieve(); ASSERT(proxy); - v8::Handle<v8::Value> result = proxy->CallFunction(callback, object, 1, args.get()); + v8::Handle<v8::Value> result = proxy->callFunction(callback, object, 1, args.get()); if (exceptionCatcher.HasCaught()) { state->setException(exceptionCatcher.Exception()); diff --git a/WebCore/bindings/v8/V8ObjectEventListener.cpp b/WebCore/bindings/v8/V8ObjectEventListener.cpp index 584962a..f10766c 100644 --- a/WebCore/bindings/v8/V8ObjectEventListener.cpp +++ b/WebCore/bindings/v8/V8ObjectEventListener.cpp @@ -45,7 +45,7 @@ static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* par if (frame) { V8Proxy* proxy = V8Proxy::retrieve(frame); if (proxy) - proxy->RemoveObjectEventListener(listener); + proxy->objectListeners()->remove(listener); // Because the listener is no longer in the list, it must be disconnected from the frame to avoid dangling frame pointer // in the destructor. @@ -54,6 +54,23 @@ static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* par listener->disposeListenerObject(); } +// An object event listener wrapper only holds a weak reference to the +// JS function. A strong reference can create a cycle. +// +// The lifetime of these objects is bounded by the life time of the JS +// wrapper of XHR or Node. So we can create a hidden reference from +// the JS wrapper to to its JS function. +// +// (map) +// XHR or Node <---------- JS_wrapper +// | (hidden) : ^ +// V V : (may be reachable by closure) +// V8_listener --------> JS_function +// (weak) <-- may create a cycle if it is strong +// +// The persistent reference is made weak in the constructor of +// V8ObjectEventListener. + V8ObjectEventListener::V8ObjectEventListener(Frame* frame, v8::Local<v8::Object> listener, bool isInline) : V8EventListener(frame, listener, isInline) { @@ -66,7 +83,7 @@ V8ObjectEventListener::~V8ObjectEventListener() ASSERT(!m_listener.IsEmpty()); V8Proxy* proxy = V8Proxy::retrieve(m_frame); if (proxy) - proxy->RemoveObjectEventListener(this); + proxy->objectListeners()->remove(this); } disposeListenerObject(); diff --git a/WebCore/bindings/v8/V8ObjectEventListener.h b/WebCore/bindings/v8/V8ObjectEventListener.h index 501bdac..3c5ae10 100644 --- a/WebCore/bindings/v8/V8ObjectEventListener.h +++ b/WebCore/bindings/v8/V8ObjectEventListener.h @@ -47,6 +47,8 @@ namespace WebCore { return adoptRef(new V8ObjectEventListener(frame, listener, isInline)); } + virtual bool isObjectListener() const { return true; } + private: V8ObjectEventListener(Frame*, v8::Local<v8::Object> listener, bool isInline); virtual ~V8ObjectEventListener(); diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp new file mode 100644 index 0000000..02bf086 --- /dev/null +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -0,0 +1,1279 @@ +/* + * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8Proxy.h" + +#include "ChromiumBridge.h" +#include "CSSMutableStyleDeclaration.h" +#include "DOMObjectsInclude.h" +#include "DocumentLoader.h" +#include "FrameLoaderClient.h" +#include "ScriptController.h" +#include "V8Binding.h" +#include "V8Collection.h" +#include "V8ConsoleMessage.h" +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8DOMWindow.h" +#include "V8HiddenPropertyName.h" +#include "V8Index.h" +#include "V8IsolatedWorld.h" + +#include <algorithm> +#include <utility> +#include <v8.h> +#include <v8-debug.h> +#include <wtf/Assertions.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> + +namespace WebCore { + +v8::Persistent<v8::Context> V8Proxy::m_utilityContext; + +// Static list of registered extensions +V8ExtensionList V8Proxy::m_extensions; + +const char* V8Proxy::kContextDebugDataType = "type"; +const char* V8Proxy::kContextDebugDataValue = "value"; + +void batchConfigureAttributes(v8::Handle<v8::ObjectTemplate> instance, v8::Handle<v8::ObjectTemplate> proto, const BatchedAttribute* attributes, size_t attributeCount) +{ + for (size_t i = 0; i < attributeCount; ++i) { + const BatchedAttribute* attribute = &attributes[i]; + (attribute->onProto ? proto : instance)->SetAccessor(v8::String::New(attribute->name), + attribute->getter, + attribute->setter, + attribute->data == V8ClassIndex::INVALID_CLASS_INDEX ? v8::Handle<v8::Value>() : v8::Integer::New(V8ClassIndex::ToInt(attribute->data)), + attribute->settings, + attribute->attribute); + } +} + +void batchConfigureConstants(v8::Handle<v8::FunctionTemplate> functionDescriptor, v8::Handle<v8::ObjectTemplate> proto, const BatchedConstant* constants, size_t constantCount) +{ + for (size_t i = 0; i < constantCount; ++i) { + const BatchedConstant* constant = &constants[i]; + functionDescriptor->Set(v8::String::New(constant->name), v8::Integer::New(constant->value), v8::ReadOnly); + proto->Set(v8::String::New(constant->name), v8::Integer::New(constant->value), v8::ReadOnly); + } +} + +typedef HashMap<Node*, v8::Object*> DOMNodeMap; +typedef HashMap<void*, v8::Object*> DOMObjectMap; + +#if ENABLE(SVG) +// Map of SVG objects with contexts to their contexts +static HashMap<void*, SVGElement*>& svgObjectToContextMap() +{ + typedef HashMap<void*, SVGElement*> SvgObjectToContextMap; + DEFINE_STATIC_LOCAL(SvgObjectToContextMap, staticSvgObjectToContextMap, ()); + return staticSvgObjectToContextMap; +} + +void V8Proxy::setSVGContext(void* object, SVGElement* context) +{ + if (!object) + return; + + SVGElement* oldContext = svgObjectToContextMap().get(object); + + if (oldContext == context) + return; + + if (oldContext) + oldContext->deref(); + + if (context) + context->ref(); + + svgObjectToContextMap().set(object, context); +} + +SVGElement* V8Proxy::svgContext(void* object) +{ + return svgObjectToContextMap().get(object); +} + +#endif + +typedef HashMap<int, v8::FunctionTemplate*> FunctionTemplateMap; + +bool AllowAllocation::m_current = false; + +void logInfo(Frame* frame, const String& message, const String& url) +{ + Page* page = frame->page(); + if (!page) + return; + V8ConsoleMessage consoleMessage(message, url, 0); + consoleMessage.dispatchNow(page); +} + +enum DelayReporting { + ReportLater, + ReportNow +}; + +static void reportUnsafeAccessTo(Frame* target, DelayReporting delay) +{ + ASSERT(target); + Document* targetDocument = target->document(); + if (!targetDocument) + return; + + Frame* source = V8Proxy::retrieveFrameForEnteredContext(); + if (!source || !source->document()) + return; // Ignore error if the source document is gone. + + Document* sourceDocument = source->document(); + + // FIXME: This error message should contain more specifics of why the same + // origin check has failed. + String str = String::format("Unsafe JavaScript attempt to access frame " + "with URL %s from frame with URL %s. " + "Domains, protocols and ports must match.\n", + targetDocument->url().string().utf8().data(), + sourceDocument->url().string().utf8().data()); + + // Build a console message with fake source ID and line number. + const String kSourceID = ""; + const int kLineNumber = 1; + V8ConsoleMessage message(str, kSourceID, kLineNumber); + + if (delay == ReportNow) { + // NOTE: Safari prints the message in the target page, but it seems like + // it should be in the source page. Even for delayed messages, we put it in + // the source page; see V8ConsoleMessage::processDelayed(). + message.dispatchNow(source->page()); + } else { + ASSERT(delay == ReportLater); + // We cannot safely report the message eagerly, because this may cause + // allocations and GCs internally in V8 and we cannot handle that at this + // point. Therefore we delay the reporting. + message.dispatchLater(); + } +} + +static void reportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data) +{ + Frame* target = V8Custom::GetTargetFrame(host, data); + if (target) + reportUnsafeAccessTo(target, ReportLater); +} + +static void handleFatalErrorInV8() +{ + // FIXME: We temporarily deal with V8 internal error situations + // such as out-of-memory by crashing the renderer. + CRASH(); +} + +static void reportFatalErrorInV8(const char* location, const char* message) +{ + // V8 is shutdown, we cannot use V8 api. + // The only thing we can do is to disable JavaScript. + // FIXME: clean up V8Proxy and disable JavaScript. + printf("V8 error: %s (%s)\n", message, location); + handleFatalErrorInV8(); +} + +V8Proxy::~V8Proxy() +{ + clearForClose(); + destroyGlobal(); +} + +void V8Proxy::destroyGlobal() +{ + if (!m_global.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_global); +#endif + m_global.Dispose(); + m_global.Clear(); + } +} + +static void disconnectEventListenersInList(V8EventListenerList& list) +{ + V8EventListenerList::iterator it = list.begin(); + while (it != list.end()) { + (*it)->disconnectFrame(); + ++it; + } + list.clear(); +} + +void V8Proxy::disconnectEventListeners() +{ + disconnectEventListenersInList(m_eventListeners); + disconnectEventListenersInList(m_objectListeners); +} + +v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine) +{ + const uint16_t* fileNameString = fromWebCoreString(fileName); + v8::Handle<v8::String> name = v8::String::New(fileNameString, fileName.length()); + v8::Handle<v8::Integer> line = v8::Integer::New(baseLine); + v8::ScriptOrigin origin(name, line); + v8::Handle<v8::Script> script = v8::Script::Compile(code, &origin); + return script; +} + +bool V8Proxy::handleOutOfMemory() +{ + v8::Local<v8::Context> context = v8::Context::GetCurrent(); + + if (!context->HasOutOfMemoryException()) + return false; + + // Warning, error, disable JS for this frame? + Frame* frame = V8Proxy::retrieveFrame(context); + + V8Proxy* proxy = V8Proxy::retrieve(frame); + if (proxy) { + // Clean m_context, and event handlers. + proxy->clearForClose(); + + proxy->destroyGlobal(); + } + + ChromiumBridge::notifyJSOutOfMemory(frame); + + // Disable JS. + Settings* settings = frame->settings(); + ASSERT(settings); + settings->setJavaScriptEnabled(false); + + return true; +} + +void V8Proxy::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup) +{ + initContextIfNeeded(); + V8IsolatedWorld::evaluate(sources, this, extensionGroup); +} + +void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) +{ + initContextIfNeeded(); + + v8::HandleScope handleScope; + + // Set up the DOM window as the prototype of the new global object. + v8::Handle<v8::Context> windowContext = m_context; + v8::Handle<v8::Object> windowGlobal = windowContext->Global(); + v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, windowGlobal); + + ASSERT(V8DOMWrapper::convertDOMWrapperToNative<DOMWindow>(windowWrapper) == m_frame->domWindow()); + + v8::Persistent<v8::Context> context = createNewContext(v8::Handle<v8::Object>(), extensionGroup); + v8::Context::Scope contextScope(context); + + // Setup context id for JS debugger. + v8::Handle<v8::Object> contextData = v8::Object::New(); + v8::Handle<v8::Value> windowContextData = windowContext->GetData(); + if (windowContextData->IsObject()) { + v8::Handle<v8::String> propertyName = v8::String::New(kContextDebugDataValue); + contextData->Set(propertyName, v8::Object::Cast(*windowContextData)->Get(propertyName)); + } + contextData->Set(v8::String::New(kContextDebugDataType), v8::String::New("injected")); + context->SetData(contextData); + + v8::Handle<v8::Object> global = context->Global(); + + v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); + global->Set(implicitProtoString, windowWrapper); + + // Give the code running in the new context a way to get access to the + // original context. + global->Set(v8::String::New("contentWindow"), windowGlobal); + + m_frame->loader()->client()->didCreateIsolatedScriptContext(); + + // Run code in the new context. + for (size_t i = 0; i < sources.size(); ++i) + evaluate(sources[i], 0); + + // Using the default security token means that the canAccess is always + // called, which is slow. + // FIXME: Use tokens where possible. This will mean keeping track of all + // created contexts so that they can all be updated when the document domain + // changes. + context->UseDefaultSecurityToken(); + context.Dispose(); +} + +v8::Local<v8::Value> V8Proxy::evaluate(const ScriptSourceCode& source, Node* node) +{ + ASSERT(v8::Context::InContext()); + + // Compile the script. + v8::Local<v8::String> code = v8ExternalString(source.source()); + ChromiumBridge::traceEventBegin("v8.compile", node, ""); + + // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at + // 1, whereas v8 starts at 0. + v8::Handle<v8::Script> script = compileScript(code, source.url(), source.startLine() - 1); + ChromiumBridge::traceEventEnd("v8.compile", node, ""); + + ChromiumBridge::traceEventBegin("v8.run", node, ""); + v8::Local<v8::Value> result; + { + // Isolate exceptions that occur when executing the code. These + // exceptions should not interfere with javascript code we might + // evaluate from C++ when returning from here. + v8::TryCatch tryCatch; + tryCatch.SetVerbose(true); + + // Set inlineCode to true for <a href="javascript:doSomething()"> + // and false for <script>doSomething</script>. We make a rough guess at + // this based on whether the script source has a URL. + result = runScript(script, source.url().string().isNull()); + } + ChromiumBridge::traceEventEnd("v8.run", node, ""); + return result; +} + +v8::Local<v8::Value> V8Proxy::runScript(v8::Handle<v8::Script> script, bool isInlineCode) +{ + if (script.IsEmpty()) + return notHandledByInterceptor(); + + // Compute the source string and prevent against infinite recursion. + if (m_recursion >= kMaxRecursionDepth) { + v8::Local<v8::String> code = v8ExternalString("throw RangeError('Recursion too deep')"); + // FIXME: Ideally, we should be able to re-use the origin of the + // script passed to us as the argument instead of using an empty string + // and 0 baseLine. + script = compileScript(code, "", 0); + } + + if (handleOutOfMemory()) + ASSERT(script.IsEmpty()); + + if (script.IsEmpty()) + return notHandledByInterceptor(); + + // Save the previous value of the inlineCode flag and update the flag for + // the duration of the script invocation. + bool previousInlineCode = inlineCode(); + setInlineCode(isInlineCode); + + // Run the script and keep track of the current recursion depth. + v8::Local<v8::Value> result; + { + V8ConsoleMessage::Scope scope; + m_recursion++; + + // See comment in V8Proxy::callFunction. + m_frame->keepAlive(); + + result = script->Run(); + m_recursion--; + } + + if (handleOutOfMemory()) + ASSERT(result.IsEmpty()); + + // Handle V8 internal error situation (Out-of-memory). + if (result.IsEmpty()) + return notHandledByInterceptor(); + + // Restore inlineCode flag. + setInlineCode(previousInlineCode); + + if (v8::V8::IsDead()) + handleFatalErrorInV8(); + + return result; +} + +v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]) +{ + // For now, we don't put any artificial limitations on the depth + // of recursion that stems from calling functions. This is in + // contrast to the script evaluations. + v8::Local<v8::Value> result; + { + V8ConsoleMessage::Scope scope; + + // Evaluating the JavaScript could cause the frame to be deallocated, + // so we start the keep alive timer here. + // Frame::keepAlive method adds the ref count of the frame and sets a + // timer to decrease the ref count. It assumes that the current JavaScript + // execution finishs before firing the timer. + m_frame->keepAlive(); + + result = function->Call(receiver, argc, args); + } + + if (v8::V8::IsDead()) + handleFatalErrorInV8(); + + return result; +} + +v8::Local<v8::Value> V8Proxy::newInstance(v8::Handle<v8::Function> constructor, int argc, v8::Handle<v8::Value> args[]) +{ + // No artificial limitations on the depth of recursion, see comment in + // V8Proxy::callFunction. + v8::Local<v8::Value> result; + { + V8ConsoleMessage::Scope scope; + + // See comment in V8Proxy::callFunction. + m_frame->keepAlive(); + + result = constructor->NewInstance(argc, args); + } + + if (v8::V8::IsDead()) + handleFatalErrorInV8(); + + return result; +} + +v8::Local<v8::Object> V8Proxy::createWrapperFromCache(V8ClassIndex::V8WrapperType type) +{ + int classIndex = V8ClassIndex::ToInt(type); + v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex)); + if (!clone.IsEmpty()) + return clone; + + // Not in cache. + initContextIfNeeded(); + v8::Context::Scope scope(m_context); + v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(m_context)); + v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); + if (!instance.IsEmpty()) { + m_wrapperBoilerplates->Set(v8::Integer::New(classIndex), instance); + return instance->Clone(); + } + return notHandledByInterceptor(); +} + +bool V8Proxy::isContextInitialized() +{ + // m_context, m_global, and m_wrapperBoilerplates should + // all be non-empty if if m_context is non-empty. + ASSERT(m_context.IsEmpty() || !m_global.IsEmpty()); + ASSERT(m_context.IsEmpty() || !m_wrapperBoilerplates.IsEmpty()); + return !m_context.IsEmpty(); +} + +DOMWindow* V8Proxy::retrieveWindow(v8::Handle<v8::Context> context) +{ + v8::Handle<v8::Object> global = context->Global(); + ASSERT(!global.IsEmpty()); + global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, global); + ASSERT(!global.IsEmpty()); + return V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, global); +} + +Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context) +{ + return retrieveWindow(context)->frame(); +} + +Frame* V8Proxy::retrieveFrameForEnteredContext() +{ + v8::Handle<v8::Context> context = v8::Context::GetEntered(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); +} + +Frame* V8Proxy::retrieveFrameForCurrentContext() +{ + v8::Handle<v8::Context> context = v8::Context::GetCurrent(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); +} + +Frame* V8Proxy::retrieveFrameForCallingContext() +{ + v8::Handle<v8::Context> context = v8::Context::GetCalling(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); +} + +V8Proxy* V8Proxy::retrieve() +{ + DOMWindow* window = retrieveWindow(currentContext()); + ASSERT(window); + return retrieve(window->frame()); +} + +V8Proxy* V8Proxy::retrieve(Frame* frame) +{ + if (!frame) + return 0; + return frame->script()->isEnabled() ? frame->script()->proxy() : 0; +} + +V8Proxy* V8Proxy::retrieve(ScriptExecutionContext* context) +{ + if (!context->isDocument()) + return 0; + return retrieve(static_cast<Document*>(context)->frame()); +} + +void V8Proxy::disconnectFrame() +{ + disconnectEventListeners(); +} + +bool V8Proxy::isEnabled() +{ + Settings* settings = m_frame->settings(); + if (!settings) + return false; + + // In the common case, JavaScript is enabled and we're done. + if (settings->isJavaScriptEnabled()) + return true; + + // If JavaScript has been disabled, we need to look at the frame to tell + // whether this script came from the web or the embedder. Scripts from the + // embedder are safe to run, but scripts from the other sources are + // disallowed. + Document* document = m_frame->document(); + if (!document) + return false; + + SecurityOrigin* origin = document->securityOrigin(); + if (origin->protocol().isEmpty()) + return false; // Uninitialized document + + if (origin->protocol() == "http" || origin->protocol() == "https") + return false; // Web site + + // FIXME: the following are application decisions, and they should + // not be made at this layer. instead, we should bridge out to the + // embedder to allow them to override policy here. + + if (origin->protocol() == ChromiumBridge::uiResourceProtocol()) + return true; // Embedder's scripts are ok to run + + // If the scheme is ftp: or file:, an empty file name indicates a directory + // listing, which requires JavaScript to function properly. + const char* kDirProtocols[] = { "ftp", "file" }; + for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { + if (origin->protocol() == kDirProtocols[i]) { + const KURL& url = document->url(); + return url.pathAfterLastSlash() == url.pathEnd(); + } + } + + return false; // Other protocols fall through to here +} + +void V8Proxy::updateDocumentWrapper(v8::Handle<v8::Value> wrapper) +{ + clearDocumentWrapper(); + + ASSERT(m_document.IsEmpty()); + m_document = v8::Persistent<v8::Value>::New(wrapper); +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_document); +#endif +} + +void V8Proxy::clearDocumentWrapper() +{ + if (!m_document.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_document); +#endif + m_document.Dispose(); + m_document.Clear(); + } +} + +void V8Proxy::updateDocumentWrapperCache() +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(context()); + + // If the document has no frame, NodeToV8Object might get the + // document wrapper for a document that is about to be deleted. + // If the ForceSet below causes a garbage collection, the document + // might get deleted and the global handle for the document + // wrapper cleared. Using the cleared global handle will lead to + // crashes. In this case we clear the cache and let the DOMWindow + // accessor handle access to the document. + if (!m_frame->document()->frame()) { + clearDocumentWrapperCache(); + return; + } + + v8::Handle<v8::Value> documentWrapper = V8DOMWrapper::convertNodeToV8Object(m_frame->document()); + + // If instantiation of the document wrapper fails, clear the cache + // and let the DOMWindow accessor handle access to the document. + if (documentWrapper.IsEmpty()) { + clearDocumentWrapperCache(); + return; + } + m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); +} + +void V8Proxy::clearDocumentWrapperCache() +{ + ASSERT(!m_context.IsEmpty()); + m_context->Global()->ForceDelete(v8::String::New("document")); +} + +void V8Proxy::disposeContextHandles() +{ + if (!m_context.IsEmpty()) { + m_frame->loader()->client()->didDestroyScriptContextForFrame(); + m_context.Dispose(); + m_context.Clear(); + } + + if (!m_wrapperBoilerplates.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_wrapperBoilerplates); +#endif + m_wrapperBoilerplates.Dispose(); + m_wrapperBoilerplates.Clear(); + } +} + +void V8Proxy::clearForClose() +{ + if (!m_context.IsEmpty()) { + v8::HandleScope handleScope; + + clearDocumentWrapper(); + disposeContextHandles(); + } +} + +void V8Proxy::clearForNavigation() +{ + disconnectEventListeners(); + + if (!m_context.IsEmpty()) { + v8::HandleScope handle; + clearDocumentWrapper(); + + v8::Context::Scope contextScope(m_context); + + // Clear the document wrapper cache before turning on access checks on + // the old DOMWindow wrapper. This way, access to the document wrapper + // will be protected by the security checks on the DOMWindow wrapper. + clearDocumentWrapperCache(); + + // Turn on access check on the old DOMWindow wrapper. + v8::Handle<v8::Object> wrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global); + ASSERT(!wrapper.IsEmpty()); + wrapper->TurnOnAccessCheck(); + + // Separate the context from its global object. + m_context->DetachGlobal(); + + disposeContextHandles(); + } +} + +void V8Proxy::setSecurityToken() +{ + Document* document = m_frame->document(); + // Setup security origin and security token. + if (!document) { + m_context->UseDefaultSecurityToken(); + return; + } + + // Ask the document's SecurityOrigin to generate a security token. + // If two tokens are equal, then the SecurityOrigins canAccess each other. + // If two tokens are not equal, then we have to call canAccess. + // Note: we can't use the HTTPOrigin if it was set from the DOM. + SecurityOrigin* origin = document->securityOrigin(); + String token; + if (!origin->domainWasSetInDOM()) + token = document->securityOrigin()->toString(); + + // An empty or "null" token means we always have to call + // canAccess. The toString method on securityOrigins returns the + // string "null" for empty security origins and for security + // origins that should only allow access to themselves. In this + // case, we use the global object as the security token to avoid + // calling canAccess when a script accesses its own objects. + if (token.isEmpty() || token == "null") { + m_context->UseDefaultSecurityToken(); + return; + } + + CString utf8Token = token.utf8(); + // NOTE: V8 does identity comparison in fast path, must use a symbol + // as the security token. + m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length())); +} + +void V8Proxy::updateDocument() +{ + if (!m_frame->document()) + return; + + if (m_global.IsEmpty()) + return; + + // There is an existing JavaScript wrapper for the global object + // of this frame. JavaScript code in other frames might hold a + // reference to this wrapper. We eagerly initialize the JavaScript + // context for the new document to make property access on the + // global object wrapper succeed. + initContextIfNeeded(); + + // We have a new document and we need to update the cache. + updateDocumentWrapperCache(); + + updateSecurityOrigin(); +} + +void V8Proxy::updateSecurityOrigin() +{ + v8::HandleScope scope; + setSecurityToken(); +} + +// Same origin policy implementation: +// +// Same origin policy prevents JS code from domain A access JS & DOM objects +// in a different domain B. There are exceptions and several objects are +// accessible by cross-domain code. For example, the window.frames object is +// accessible by code from a different domain, but window.document is not. +// +// The binding code sets security check callbacks on a function template, +// and accessing instances of the template calls the callback function. +// The callback function checks same origin policy. +// +// Callback functions are expensive. V8 uses a security token string to do +// fast access checks for the common case where source and target are in the +// same domain. A security token is a string object that represents +// the protocol/url/port of a domain. +// +// There are special cases where a security token matching is not enough. +// For example, JavaScript can set its domain to a super domain by calling +// document.setDomain(...). In these cases, the binding code can reset +// a context's security token to its global object so that the fast access +// check will always fail. + +// Check if the current execution context can access a target frame. +// First it checks same domain policy using the lexical context +// +// This is equivalent to KJS::Window::allowsAccessFrom(ExecState*, String&). +bool V8Proxy::canAccessPrivate(DOMWindow* targetWindow) +{ + ASSERT(targetWindow); + + String message; + + DOMWindow* originWindow = retrieveWindow(currentContext()); + if (originWindow == targetWindow) + return true; + + if (!originWindow) + return false; + + const SecurityOrigin* activeSecurityOrigin = originWindow->securityOrigin(); + const SecurityOrigin* targetSecurityOrigin = targetWindow->securityOrigin(); + + // We have seen crashes were the security origin of the target has not been + // initialized. Defend against that. + if (!targetSecurityOrigin) + return false; + + if (activeSecurityOrigin->canAccess(targetSecurityOrigin)) + return true; + + // Allow access to a "about:blank" page if the dynamic context is a + // detached context of the same frame as the blank page. + if (targetSecurityOrigin->isEmpty() && originWindow->frame() == targetWindow->frame()) + return true; + + return false; +} + +bool V8Proxy::canAccessFrame(Frame* target, bool reportError) +{ + // The subject is detached from a frame, deny accesses. + if (!target) + return false; + + if (!canAccessPrivate(target->domWindow())) { + if (reportError) + reportUnsafeAccessTo(target, ReportNow); + return false; + } + return true; +} + +bool V8Proxy::checkNodeSecurity(Node* node) +{ + if (!node) + return false; + + Frame* target = node->document()->frame(); + + if (!target) + return false; + + return canAccessFrame(target, true); +} + +v8::Persistent<v8::Context> V8Proxy::createNewContext(v8::Handle<v8::Object> global, int extensionGroup) +{ + v8::Persistent<v8::Context> result; + + // The activeDocumentLoader pointer could be NULL during frame shutdown. + if (!m_frame->loader()->activeDocumentLoader()) + return result; + + // Create a new environment using an empty template for the shadow + // object. Reuse the global object if one has been created earlier. + v8::Persistent<v8::ObjectTemplate> globalTemplate = V8DOMWindow::GetShadowObjectTemplate(); + if (globalTemplate.IsEmpty()) + return result; + + // Install a security handler with V8. + globalTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW)); + + // Dynamically tell v8 about our extensions now. + OwnArrayPtr<const char*> extensionNames(new const char*[m_extensions.size()]); + int index = 0; + for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) { + if (it->group && it->group != extensionGroup) + continue; + + // Note: we check the loader URL here instead of the document URL + // because we might be currently loading an URL into a blank page. + // See http://code.google.com/p/chromium/issues/detail?id=10924 + if (it->scheme.length() > 0 && (it->scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || it->scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol())) + continue; + + extensionNames[index++] = it->extension->name(); + } + v8::ExtensionConfiguration extensions(index, extensionNames.get()); + result = v8::Context::New(&extensions, globalTemplate, global); + + return result; +} + +bool V8Proxy::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window) +{ + v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); + if (implicitProtoString.IsEmpty()) + return false; + + // Create a new JS window object and use it as the prototype for the shadow global object. + v8::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(V8ClassIndex::DOMWINDOW, getHiddenObjectPrototype(context)); + v8::Local<v8::Object> jsWindow = SafeAllocation::newInstance(windowConstructor); + // Bail out if allocation failed. + if (jsWindow.IsEmpty()) + return false; + + // Wrap the window. + V8DOMWrapper::setDOMWrapper(jsWindow, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); + + window->ref(); + V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow)); + + // Insert the window instance as the prototype of the shadow object. + v8::Handle<v8::Object> v8Global = context->Global(); + v8Global->Set(implicitProtoString, jsWindow); + return true; +} + +// Create a new environment and setup the global object. +// +// The global object corresponds to a DOMWindow instance. However, to +// allow properties of the JS DOMWindow instance to be shadowed, we +// use a shadow object as the global object and use the JS DOMWindow +// instance as the prototype for that shadow object. The JS DOMWindow +// instance is undetectable from javascript code because the __proto__ +// accessors skip that object. +// +// The shadow object and the DOMWindow instance are seen as one object +// from javascript. The javascript object that corresponds to a +// DOMWindow instance is the shadow object. When mapping a DOMWindow +// instance to a V8 object, we return the shadow object. +// +// To implement split-window, see +// 1) https://bugs.webkit.org/show_bug.cgi?id=17249 +// 2) https://wiki.mozilla.org/Gecko:SplitWindow +// 3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639 +// we need to split the shadow object further into two objects: +// an outer window and an inner window. The inner window is the hidden +// prototype of the outer window. The inner window is the default +// global object of the context. A variable declared in the global +// scope is a property of the inner window. +// +// The outer window sticks to a Frame, it is exposed to JavaScript +// via window.window, window.self, window.parent, etc. The outer window +// has a security token which is the domain. The outer window cannot +// have its own properties. window.foo = 'x' is delegated to the +// inner window. +// +// When a frame navigates to a new page, the inner window is cut off +// the outer window, and the outer window identify is preserved for +// the frame. However, a new inner window is created for the new page. +// If there are JS code holds a closure to the old inner window, +// it won't be able to reach the outer window via its global object. +void V8Proxy::initContextIfNeeded() +{ + // Bail out if the context has already been initialized. + if (!m_context.IsEmpty()) + return; + + // Create a handle scope for all local handles. + v8::HandleScope handleScope; + + // Setup the security handlers and message listener. This only has + // to be done once. + static bool isV8Initialized = false; + if (!isV8Initialized) { + // Tells V8 not to call the default OOM handler, binding code + // will handle it. + v8::V8::IgnoreOutOfMemoryException(); + v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); + + v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue); + v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue); + + v8::V8::AddMessageListener(&V8ConsoleMessage::handler); + + v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess); + + isV8Initialized = true; + } + + m_context = createNewContext(m_global, 0); + if (m_context.IsEmpty()) + return; + + // Starting from now, use local context only. + v8::Local<v8::Context> v8Context = context(); + v8::Context::Scope contextScope(v8Context); + + // Store the first global object created so we can reuse it. + if (m_global.IsEmpty()) { + m_global = v8::Persistent<v8::Object>::New(v8Context->Global()); + // Bail out if allocation of the first global objects fails. + if (m_global.IsEmpty()) { + disposeContextHandles(); + return; + } +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_global); +#endif + } + + installHiddenObjectPrototype(m_context); + m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT)); + // Bail out if allocation failed. + if (m_wrapperBoilerplates.IsEmpty()) { + disposeContextHandles(); + return; + } +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates); +#endif + + if (!installDOMWindow(v8Context, m_frame->domWindow())) + disposeContextHandles(); + + updateDocument(); + + setSecurityToken(); + + m_frame->loader()->client()->didCreateScriptContextForFrame(); + m_frame->loader()->dispatchWindowObjectAvailable(); +} + +void V8Proxy::setDOMException(int exceptionCode) +{ + if (exceptionCode <= 0) + return; + + ExceptionCodeDescription description; + getExceptionCodeDescription(exceptionCode, description); + + v8::Handle<v8::Value> exception; + switch (description.type) { + case DOMExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMCOREEXCEPTION, DOMCoreException::create(description)); + break; + case RangeExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::RANGEEXCEPTION, RangeException::create(description)); + break; + case EventExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::EVENTEXCEPTION, EventException::create(description)); + break; + case XMLHttpRequestExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::XMLHTTPREQUESTEXCEPTION, XMLHttpRequestException::create(description)); + break; +#if ENABLE(SVG) + case SVGExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGEXCEPTION, SVGException::create(description)); + break; +#endif +#if ENABLE(XPATH) + case XPathExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::XPATHEXCEPTION, XPathException::create(description)); + break; +#endif + } + + ASSERT(!exception.IsEmpty()); + v8::ThrowException(exception); +} + +v8::Handle<v8::Value> V8Proxy::throwError(ErrorType type, const char* message) +{ + switch (type) { + case RangeError: + return v8::ThrowException(v8::Exception::RangeError(v8String(message))); + case ReferenceError: + return v8::ThrowException(v8::Exception::ReferenceError(v8String(message))); + case SyntaxError: + return v8::ThrowException(v8::Exception::SyntaxError(v8String(message))); + case TypeError: + return v8::ThrowException(v8::Exception::TypeError(v8String(message))); + case GeneralError: + return v8::ThrowException(v8::Exception::Error(v8String(message))); + default: + ASSERT_NOT_REACHED(); + return notHandledByInterceptor(); + } +} + +v8::Local<v8::Context> V8Proxy::context(Frame* frame) +{ + v8::Local<v8::Context> context = V8Proxy::mainWorldContext(frame); + if (context.IsEmpty()) + return v8::Local<v8::Context>(); + + if (V8IsolatedWorld* world = V8IsolatedWorld::getEntered()) { + context = v8::Local<v8::Context>::New(world->context()); + if (frame != V8Proxy::retrieveFrame(context)) + return v8::Local<v8::Context>(); + } + + return context; +} + +v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame) +{ + V8Proxy* proxy = retrieve(frame); + if (!proxy) + return v8::Local<v8::Context>(); + + proxy->initContextIfNeeded(); + return proxy->context(); +} + +v8::Local<v8::Context> V8Proxy::currentContext() +{ + return v8::Context::GetCurrent(); +} + +v8::Handle<v8::Value> V8Proxy::checkNewLegal(const v8::Arguments& args) +{ + if (!AllowAllocation::m_current) + return throwError(TypeError, "Illegal constructor"); + + return args.This(); +} + +void V8Proxy::bindJsObjectToWindow(Frame* frame, const char* name, int type, v8::Handle<v8::FunctionTemplate> descriptor, void* impl) +{ + // Get environment. + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); + if (v8Context.IsEmpty()) + return; // JS not enabled. + + v8::Context::Scope scope(v8Context); + v8::Handle<v8::Object> instance = descriptor->GetFunction(); + V8DOMWrapper::setDOMWrapper(instance, type, impl); + + v8::Handle<v8::Object> global = v8Context->Global(); + global->Set(v8::String::New(name), instance); +} + +void V8Proxy::processConsoleMessages() +{ + V8ConsoleMessage::processDelayed(); +} + +// Create the utility context for holding JavaScript functions used internally +// which are not visible to JavaScript executing on the page. +void V8Proxy::createUtilityContext() +{ + ASSERT(m_utilityContext.IsEmpty()); + + v8::HandleScope scope; + v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); + m_utilityContext = v8::Context::New(0, globalTemplate); + v8::Context::Scope contextScope(m_utilityContext); + + // Compile JavaScript function for retrieving the source line of the top + // JavaScript stack frame. + DEFINE_STATIC_LOCAL(const char*, frameSourceLineSource, + ("function frameSourceLine(exec_state) {" + " return exec_state.frame(0).sourceLine();" + "}")); + v8::Script::Compile(v8::String::New(frameSourceLineSource))->Run(); + + // Compile JavaScript function for retrieving the source name of the top + // JavaScript stack frame. + DEFINE_STATIC_LOCAL(const char*, frameSourceNameSource, + ("function frameSourceName(exec_state) {" + " var frame = exec_state.frame(0);" + " if (frame.func().resolved() && " + " frame.func().script() && " + " frame.func().script().name()) {" + " return frame.func().script().name();" + " }" + "}")); + v8::Script::Compile(v8::String::New(frameSourceNameSource))->Run(); +} + +int V8Proxy::sourceLineNumber() +{ + v8::HandleScope scope; + v8::Handle<v8::Context> v8UtilityContext = V8Proxy::utilityContext(); + if (v8UtilityContext.IsEmpty()) + return 0; + v8::Context::Scope contextScope(v8UtilityContext); + v8::Handle<v8::Function> frameSourceLine; + frameSourceLine = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceLine"))); + if (frameSourceLine.IsEmpty()) + return 0; + v8::Handle<v8::Value> result = v8::Debug::Call(frameSourceLine); + if (result.IsEmpty()) + return 0; + return result->Int32Value(); +} + +String V8Proxy::sourceName() +{ + v8::HandleScope scope; + v8::Handle<v8::Context> v8UtilityContext = utilityContext(); + if (v8UtilityContext.IsEmpty()) + return String(); + v8::Context::Scope contextScope(v8UtilityContext); + v8::Handle<v8::Function> frameSourceName; + frameSourceName = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceName"))); + if (frameSourceName.IsEmpty()) + return String(); + return toWebCoreString(v8::Debug::Call(frameSourceName)); +} + +void V8Proxy::registerExtensionWithV8(v8::Extension* extension) { + // If the extension exists in our list, it was already registered with V8. + for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) { + if (it->extension == extension) + return; + } + + v8::RegisterExtension(extension); +} + +void V8Proxy::registerExtension(v8::Extension* extension, const String& schemeRestriction) +{ + registerExtensionWithV8(extension); + V8ExtensionInfo info = {schemeRestriction, 0, extension}; + m_extensions.push_back(info); +} + +void V8Proxy::registerExtension(v8::Extension* extension, int extensionGroup) +{ + registerExtensionWithV8(extension); + V8ExtensionInfo info = {String(), extensionGroup, extension}; + m_extensions.push_back(info); +} + +bool V8Proxy::setContextDebugId(int debugId) +{ + ASSERT(debugId > 0); + if (m_context.IsEmpty()) + return false; + v8::HandleScope scope; + if (!m_context->GetData()->IsUndefined()) + return false; + + v8::Context::Scope contextScope(m_context); + v8::Handle<v8::Object> contextData = v8::Object::New(); + contextData->Set(v8::String::New(kContextDebugDataType), v8::String::New("page")); + contextData->Set(v8::String::New(kContextDebugDataValue), v8::Integer::New(debugId)); + m_context->SetData(contextData); + return true; +} + +int V8Proxy::contextDebugId(v8::Handle<v8::Context> context) +{ + v8::HandleScope scope; + if (!context->GetData()->IsObject()) + return -1; + v8::Handle<v8::Value> data = context->GetData()->ToObject()->Get( v8::String::New(kContextDebugDataValue)); + return data->IsInt32() ? data->Int32Value() : -1; +} + +v8::Handle<v8::Value> V8Proxy::getHiddenObjectPrototype(v8::Handle<v8::Context> context) +{ + return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype()); +} + +void V8Proxy::installHiddenObjectPrototype(v8::Handle<v8::Context> context) +{ + v8::Handle<v8::String> objectString = v8::String::New("Object"); + v8::Handle<v8::String> prototypeString = v8::String::New("prototype"); + v8::Handle<v8::String> hiddenObjectPrototypeString = V8HiddenPropertyName::objectPrototype(); + // Bail out if allocation failed. + if (objectString.IsEmpty() || prototypeString.IsEmpty() || hiddenObjectPrototypeString.IsEmpty()) + return; + + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString)); + v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString); + + context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h index c21e0dd..caa991c 100644 --- a/WebCore/bindings/v8/V8Proxy.h +++ b/WebCore/bindings/v8/V8Proxy.h @@ -31,12 +31,437 @@ #ifndef V8Proxy_h #define V8Proxy_h -// FIXME: This is a temporary forwarding header until all bindings have migrated -// over and v8_proxy actually becomes V8Proxy. -#include "v8_proxy.h" +#include "ChromiumBridge.h" +#include "Node.h" +#include "NodeFilter.h" +#include "PlatformString.h" // for WebCore::String +#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode +#include "SecurityOrigin.h" // for WebCore::SecurityOrigin +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8DOMWrapper.h" +#include "V8EventListenerList.h" +#include "V8GCController.h" +#include "V8Index.h" +#include "V8Utilities.h" +#include <v8.h> +#include <wtf/Assertions.h> +#include <wtf/PassRefPtr.h> // so generated bindings don't have to +#include <wtf/Vector.h> + +#include <iterator> +#include <list> + +#ifdef ENABLE_DOM_STATS_COUNTERS +#define INC_STATS(name) ChromiumBridge::incrementStatsCounter(name) +#else +#define INC_STATS(name) +#endif namespace WebCore { + class CSSRule; + class CSSRuleList; + class CSSStyleDeclaration; + class CSSValue; + class CSSValueList; + class ClientRectList; + class DOMImplementation; + class DOMWindow; + class Document; + class Element; + class Event; + class EventListener; + class EventTarget; + class Frame; + class HTMLCollection; + class HTMLDocument; + class HTMLElement; + class HTMLOptionsCollection; + class MediaList; + class MimeType; + class MimeTypeArray; + class NamedNodeMap; + class Navigator; + class Node; + class NodeFilter; + class NodeList; + class Plugin; + class PluginArray; + class SVGElement; +#if ENABLE(SVG) + class SVGElementInstance; +#endif + class Screen; + class ScriptExecutionContext; +#if ENABLE(DOM_STORAGE) + class Storage; + class StorageEvent; +#endif + class String; + class StyleSheet; + class StyleSheetList; + class V8EventListener; + class V8ObjectEventListener; + + // FIXME: use standard logging facilities in WebCore. + void logInfo(Frame*, const String& message, const String& url); + + // The following Batch structs and methods are used for setting multiple + // properties on an ObjectTemplate, used from the generated bindings + // initialization (ConfigureXXXTemplate). This greatly reduces the binary + // size by moving from code driven setup to data table driven setup. + + // BatchedAttribute translates into calls to SetAccessor() on either the + // instance or the prototype ObjectTemplate, based on |onProto|. + struct BatchedAttribute { + const char* const name; + v8::AccessorGetter getter; + v8::AccessorSetter setter; + V8ClassIndex::V8WrapperType data; + v8::AccessControl settings; + v8::PropertyAttribute attribute; + bool onProto; + }; + + void batchConfigureAttributes(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::ObjectTemplate>, const BatchedAttribute*, size_t attributeCount); + + // BatchedConstant translates into calls to Set() for setting up an object's + // constants. It sets the constant on both the FunctionTemplate and the + // ObjectTemplate. PropertyAttributes is always ReadOnly. + struct BatchedConstant { + const char* const name; + int value; + }; + + void batchConfigureConstants(v8::Handle<v8::FunctionTemplate>, v8::Handle<v8::ObjectTemplate>, const BatchedConstant*, size_t constantCount); + + const int kMaxRecursionDepth = 20; + + // Information about an extension that is registered for use with V8. If + // scheme is non-empty, it contains the URL scheme the extension should be + // used with. If group is non-zero, the extension will only be loaded into + // script contexts that belong to that group. Otherwise, the extension is + // used with all schemes and contexts. + struct V8ExtensionInfo { + String scheme; + int group; + v8::Extension* extension; + }; + typedef std::list<V8ExtensionInfo> V8ExtensionList; + + class V8Proxy { + public: + // The types of javascript errors that can be thrown. + enum ErrorType { + RangeError, + ReferenceError, + SyntaxError, + TypeError, + GeneralError + }; + + explicit V8Proxy(Frame* frame) : m_frame(frame), m_inlineCode(false), m_timerCallback(false), m_recursion(0) { } + + ~V8Proxy(); + + Frame* frame() { return m_frame; } + + // Clear page-specific data, but keep the global object identify. + void clearForNavigation(); + + // Clear page-specific data before shutting down the proxy object. + void clearForClose(); + + // Update document object of the frame. + void updateDocument(); + + // Update the security origin of a document + // (e.g., after setting docoument.domain). + void updateSecurityOrigin(); + + // Destroy the global object. + void destroyGlobal(); + + // FIXME: Need comment. User Gesture related. + bool inlineCode() const { return m_inlineCode; } + void setInlineCode(bool value) { m_inlineCode = value; } + + bool timerCallback() const { return m_timerCallback; } + void setTimerCallback(bool value) { m_timerCallback = value; } + + // Has the context for this proxy been initialized? + bool isContextInitialized(); + + // Disconnects the proxy from its owner frame, + // and clears all timeouts on the DOM window. + void disconnectFrame(); + + bool isEnabled(); + + V8EventListenerList* eventListeners() { return &m_eventListeners; } + V8EventListenerList* objectListeners() { return &m_objectListeners; } + +#if ENABLE(SVG) + static void setSVGContext(void*, SVGElement*); + static SVGElement* svgContext(void*); +#endif + + void setEventHandlerLineNumber(int lineNumber) { m_handlerLineNumber = lineNumber; } + void finishedWithEvent(Event*) { } + + // Evaluate JavaScript in a new isolated world. The script gets its own + // global scope, its own prototypes for intrinsic JavaScript objects (String, + // Array, and so-on), and its own wrappers for all DOM nodes and DOM + // constructors. + void evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup); + + // Evaluate JavaScript in a new context. The script gets its own global scope + // and its own prototypes for intrinsic JavaScript objects (String, Array, + // and so-on). It shares the wrappers for all DOM nodes and DOM constructors. + void evaluateInNewContext(const Vector<ScriptSourceCode>&, int extensionGroup); + + // Evaluate a script file in the current execution environment. + // The caller must hold an execution context. + // If cannot evalute the script, it returns an error. + v8::Local<v8::Value> evaluate(const ScriptSourceCode&, Node*); + + // Run an already compiled script. + v8::Local<v8::Value> runScript(v8::Handle<v8::Script>, bool isInlineCode); + + // Call the function with the given receiver and arguments. + v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]); + + // Call the function as constructor with the given arguments. + v8::Local<v8::Value> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); + + // To create JS Wrapper objects, we create a cache of a 'boiler plate' + // object, and then simply Clone that object each time we need a new one. + // This is faster than going through the full object creation process. + v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType); + + // Returns the window object associated with a context. + static DOMWindow* retrieveWindow(v8::Handle<v8::Context>); + // Returns V8Proxy object of the currently executing context. + static V8Proxy* retrieve(); + // Returns V8Proxy object associated with a frame. + static V8Proxy* retrieve(Frame*); + // Returns V8Proxy object associated with a script execution context. + static V8Proxy* retrieve(ScriptExecutionContext*); + + // Returns the frame object of the window object associated with + // a context. + static Frame* retrieveFrame(v8::Handle<v8::Context>); + + + // The three functions below retrieve WebFrame instances relating the + // currently executing JavaScript. Since JavaScript can make function calls + // across frames, though, we need to be more precise. + // + // For example, imagine that a JS function in frame A calls a function in + // frame B, which calls native code, which wants to know what the 'active' + // frame is. + // + // The 'entered context' is the context where execution first entered the + // script engine; the context that is at the bottom of the JS function stack. + // RetrieveFrameForEnteredContext() would return Frame A in our example. + // This frame is often referred to as the "dynamic global object." + // + // The 'current context' is the context the JS engine is currently inside of; + // the context that is at the top of the JS function stack. + // RetrieveFrameForCurrentContext() would return Frame B in our example. + // This frame is often referred to as the "lexical global object." + // + // Finally, the 'calling context' is the context one below the current + // context on the JS function stack. For example, if function f calls + // function g, then the calling context will be the context associated with + // f. This context is commonly used by DOM security checks because they want + // to know who called them. + // + // If you are unsure which of these functions to use, ask abarth. + // + // NOTE: These cannot be declared as inline function, because VS complains at + // linking time. + static Frame* retrieveFrameForEnteredContext(); + static Frame* retrieveFrameForCurrentContext(); + static Frame* retrieveFrameForCallingContext(); + + // Returns V8 Context of a frame. If none exists, creates + // a new context. It is potentially slow and consumes memory. + static v8::Local<v8::Context> context(Frame*); + static v8::Local<v8::Context> mainWorldContext(Frame*); + static v8::Local<v8::Context> currentContext(); + + // If the current context causes out of memory, JavaScript setting + // is disabled and it returns true. + static bool handleOutOfMemory(); + + // Check if the active execution context can access the target frame. + static bool canAccessFrame(Frame*, bool reportError); + + // Check if it is safe to access the given node from the + // current security context. + static bool checkNodeSecurity(Node*); + + static v8::Handle<v8::Value> checkNewLegal(const v8::Arguments&); + + static v8::Handle<v8::Script> compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine); + + // If the exception code is different from zero, a DOM exception is + // schedule to be thrown. + static void setDOMException(int exceptionCode); + + // Schedule an error object to be thrown. + static v8::Handle<v8::Value> throwError(ErrorType, const char* message); + + // Create an instance of a function descriptor and set to the global object + // as a named property. Used by v8_test_shell. + static void bindJsObjectToWindow(Frame*, const char* name, int type, v8::Handle<v8::FunctionTemplate>, void*); + + template <int tag, typename T> + static v8::Handle<v8::Value> constructDOMObject(const v8::Arguments&); + + // Process any pending JavaScript console messages. + static void processConsoleMessages(); + + // Function for retrieving the line number and source name for the top + // JavaScript stack frame. + static int sourceLineNumber(); + static String sourceName(); + + // Returns a local handle of the context. + v8::Local<v8::Context> context() + { + return v8::Local<v8::Context>::New(m_context); + } + + bool setContextDebugId(int id); + static int contextDebugId(v8::Handle<v8::Context>); + + static v8::Handle<v8::Value> getHiddenObjectPrototype(v8::Handle<v8::Context>); + // WARNING: Call |installHiddenObjectPrototype| only on fresh contexts! + static void installHiddenObjectPrototype(v8::Handle<v8::Context>); + + // Registers a v8 extension to be available on webpages. The two forms + // offer various restrictions on what types of contexts the extension is + // loaded into. If a scheme is provided, only pages whose URL has the given + // scheme will match. If extensionGroup is provided, the extension will + // only be loaded into scripts run via evaluateInNewWorld with the + // matching group. Will only affect v8 contexts initialized after this + // call. Takes ownership of the v8::Extension object passed. + static void registerExtension(v8::Extension*, const String& schemeRestriction); + static void registerExtension(v8::Extension*, int extensionGroup); + + // FIXME: Separate these concerns from V8Proxy? + v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global, int extensionGroup); + static bool installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window); + + void initContextIfNeeded(); + void updateDocumentWrapper(v8::Handle<v8::Value> wrapper); + + private: + static const char* kContextDebugDataType; + static const char* kContextDebugDataValue; + + void disconnectEventListeners(); + void setSecurityToken(); + void clearDocumentWrapper(); + + // The JavaScript wrapper for the document object is cached on the global + // object for fast access. UpdateDocumentWrapperCache sets the wrapper + // for the current document on the global object. ClearDocumentWrapperCache + // deletes the document wrapper from the global object. + void updateDocumentWrapperCache(); + void clearDocumentWrapperCache(); + + // Dispose global handles of m_contexts and friends. + void disposeContextHandles(); + + static bool canAccessPrivate(DOMWindow*); + + static const char* rangeExceptionName(int exceptionCode); + static const char* eventExceptionName(int exceptionCode); + static const char* xmlHttpRequestExceptionName(int exceptionCode); + static const char* domExceptionName(int exceptionCode); + +#if ENABLE(XPATH) + static const char* xpathExceptionName(int exceptionCode); +#endif + +#if ENABLE(SVG) + static const char* svgExceptionName(int exceptionCode); +#endif + + static void createUtilityContext(); + + // Returns a local handle of the utility context. + static v8::Local<v8::Context> utilityContext() + { + if (m_utilityContext.IsEmpty()) + createUtilityContext(); + return v8::Local<v8::Context>::New(m_utilityContext); + } + + static void registerExtensionWithV8(v8::Extension*); + + Frame* m_frame; + + v8::Persistent<v8::Context> m_context; + // For each possible type of wrapper, we keep a boilerplate object. + // The boilerplate is used to create additional wrappers of the same + // type. We keep a single persistent handle to an array of the + // activated boilerplates. + v8::Persistent<v8::Array> m_wrapperBoilerplates; + + v8::Persistent<v8::Object> m_global; + v8::Persistent<v8::Value> m_document; + + // Utility context holding JavaScript functions used internally. + static v8::Persistent<v8::Context> m_utilityContext; + + int m_handlerLineNumber; + + // A list of event listeners created for this frame, + // the list gets cleared when removing all timeouts. + V8EventListenerList m_eventListeners; + + // A list of event listeners create for XMLHttpRequest object for this frame, + // the list gets cleared when removing all timeouts. + V8EventListenerList m_objectListeners; + + // True for <a href="javascript:foo()"> and false for <script>foo()</script>. + // Only valid during execution. + bool m_inlineCode; + + // True when executing from within a timer callback. Only valid during + // execution. + bool m_timerCallback; + + // Track the recursion depth to be able to avoid too deep recursion. The V8 + // engine allows much more recursion than KJS does so we need to guard against + // excessive recursion in the binding layer. + int m_recursion; + + // List of extensions registered with the context. + static V8ExtensionList m_extensions; + }; + + template <int tag, typename T> + v8::Handle<v8::Value> V8Proxy::constructDOMObject(const v8::Arguments& args) + { + if (!args.IsConstructCall()) + return throwError(V8Proxy::TypeError, "DOM object constructor cannot be called as a function."); + + // Note: it's OK to let this RefPtr go out of scope because we also call + // SetDOMWrapper(), which effectively holds a reference to obj. + RefPtr<T> obj = T::create(); + V8DOMWrapper::setDOMWrapper(args.Holder(), tag, obj.get()); + obj->ref(); + V8DOMWrapper::setJSWrapperForDOMObject(obj.get(), v8::Persistent<v8::Object>::New(args.Holder())); + return args.Holder(); + } + + // Used by an interceptor callback that it hasn't found anything to // intercept. inline static v8::Local<v8::Object> notHandledByInterceptor() @@ -48,22 +473,15 @@ namespace WebCore { { return v8::Local<v8::Boolean>(); } - - // FIXME: Remove once migration is complete. - inline static DOMWrapperMap<void>& domObjectMap() - { - return GetDOMObjectMap(); - } - - inline v8::Handle<v8::Primitive> throwError(const char* message, V8Proxy::ErrorType type = V8Proxy::TYPE_ERROR) + inline v8::Handle<v8::Primitive> throwError(const char* message, V8Proxy::ErrorType type = V8Proxy::TypeError) { - V8Proxy::ThrowError(type, message); + V8Proxy::throwError(type, message); return v8::Undefined(); } inline v8::Handle<v8::Primitive> throwError(ExceptionCode ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Undefined(); } @@ -76,7 +494,7 @@ namespace WebCore { template <class T> inline v8::Handle<v8::Object> toV8(PassRefPtr<T> object, v8::Local<v8::Object> holder) { object->ref(); - V8Proxy::SetJSWrapperForDOMObject(object.get(), v8::Persistent<v8::Object>::New(holder)); + V8DOMWrapper::setJSWrapperForDOMObject(object.get(), v8::Persistent<v8::Object>::New(holder)); return holder; } diff --git a/WebCore/bindings/v8/V8SVGPODTypeWrapper.h b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h new file mode 100644 index 0000000..b6e47af --- /dev/null +++ b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Google. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8SVGPODTypeWrapper_h +#define V8SVGPODTypeWrapper_h + +#if ENABLE(SVG) + +#include <utility> + +#include "SVGElement.h" +#include "SVGList.h" +#include "V8Proxy.h" + +#include <wtf/Assertions.h> +#include <wtf/HashFunctions.h> +#include <wtf/HashMap.h> +#include <wtf/RefCounted.h> +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +template<typename PODType> +class V8SVGPODTypeWrapper : public RefCounted<V8SVGPODTypeWrapper<PODType> > { +public: + V8SVGPODTypeWrapper() { } + virtual ~V8SVGPODTypeWrapper() { } + virtual operator PODType() = 0; + virtual void commitChange(PODType, SVGElement*) = 0; +}; + +template<typename PODType> +class V8SVGPODTypeWrapperCreatorForList : public V8SVGPODTypeWrapper<PODType> { +public: + typedef SVGPODListItem<PODType> PODListItemPtrType; + + typedef PODType (SVGPODListItem<PODType>::*GetterMethod)() const; + typedef void (SVGPODListItem<PODType>::*SetterMethod)(PODType); + + static PassRefPtr<V8SVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) + { + return adoptRef(new V8SVGPODTypeWrapperCreatorForList(creator, attributeName)); + } + + virtual ~V8SVGPODTypeWrapperCreatorForList() { } + + // Getter wrapper + virtual operator PODType() { return (m_creator.get()->*m_getter)(); } + + // Setter wrapper + virtual void commitChange(PODType type, SVGElement* context) + { + if (!m_setter) + return; + + (m_creator.get()->*m_setter)(type); + + if (context) + context->svgAttributeChanged(m_associatedAttributeName); + } + +private: + V8SVGPODTypeWrapperCreatorForList(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) + : m_creator(creator) + , m_getter(&SVGPODListItem<PODType>::value) + , m_setter(&SVGPODListItem<PODType>::setValue) + , m_associatedAttributeName(attributeName) + { + ASSERT(m_creator); + ASSERT(m_getter); + ASSERT(m_setter); + } + + // Update callbacks + RefPtr<SVGPODListItem<PODType> > m_creator; + GetterMethod m_getter; + SetterMethod m_setter; + const QualifiedName& m_associatedAttributeName; +}; + +template<typename PODType> +class V8SVGStaticPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> { +public: + static PassRefPtr<V8SVGStaticPODTypeWrapper> create(PODType type) + { + return adoptRef(new V8SVGStaticPODTypeWrapper(type)); + } + + virtual ~V8SVGStaticPODTypeWrapper() { } + + // Getter wrapper + virtual operator PODType() { return m_podType; } + + // Setter wrapper + virtual void commitChange(PODType type, SVGElement*) + { + m_podType = type; + } + +protected: + V8SVGStaticPODTypeWrapper(PODType type) + : m_podType(type) + { + } + + PODType m_podType; +}; + +template<typename PODType, typename ParentTypeArg> +class V8SVGStaticPODTypeWrapperWithPODTypeParent : public V8SVGStaticPODTypeWrapper<PODType> { +public: + typedef V8SVGPODTypeWrapper<ParentTypeArg> ParentType; + + static PassRefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent> create(PODType type, PassRefPtr<ParentType> parent) + { + return adoptRef(new V8SVGStaticPODTypeWrapperWithPODTypeParent(type, parent)); + } + + virtual void commitChange(PODType type, SVGElement* context) + { + V8SVGStaticPODTypeWrapper<PODType>::commitChange(type, context); + m_parentType->commitChange(ParentTypeArg(type), context); + } + +private: + V8SVGStaticPODTypeWrapperWithPODTypeParent(PODType type, PassRefPtr<ParentType> parent) + : V8SVGStaticPODTypeWrapper<PODType>(type) + , m_parentType(parent) + { + } + + RefPtr<ParentType> m_parentType; +}; + +template<typename PODType, typename ParentType> +class V8SVGStaticPODTypeWrapperWithParent : public V8SVGPODTypeWrapper<PODType> { +public: + typedef PODType (ParentType::*GetterMethod)() const; + typedef void (ParentType::*SetterMethod)(const PODType&); + + static PassRefPtr<V8SVGStaticPODTypeWrapperWithParent> create(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter) + { + return adoptRef(new V8SVGStaticPODTypeWrapperWithParent(parent, getter, setter)); + } + + virtual operator PODType() + { + return (m_parent.get()->*m_getter)(); + } + + virtual void commitChange(PODType type, SVGElement* context) + { + (m_parent.get()->*m_setter)(type); + } + +private: + V8SVGStaticPODTypeWrapperWithParent(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter) + : m_parent(parent) + , m_getter(getter) + , m_setter(setter) + { + ASSERT(m_parent); + ASSERT(m_getter); + ASSERT(m_setter); + } + + RefPtr<ParentType> m_parent; + GetterMethod m_getter; + SetterMethod m_setter; +}; + +template<typename PODType, typename PODTypeCreator> +class V8SVGDynamicPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> { +public: + typedef PODType (PODTypeCreator::*GetterMethod)() const; + typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (*CacheRemovalCallback)(V8SVGPODTypeWrapper<PODType>*); + + static PassRefPtr<V8SVGDynamicPODTypeWrapper> create(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) + { + return adoptRef(new V8SVGDynamicPODTypeWrapper(creator, getter, setter, cacheRemovalCallback)); + } + + virtual ~V8SVGDynamicPODTypeWrapper() { + ASSERT(m_cacheRemovalCallback); + + (*m_cacheRemovalCallback)(this); + } + + // Getter wrapper + virtual operator PODType() { return (m_creator.get()->*m_getter)(); } + + // Setter wrapper + virtual void commitChange(PODType type, SVGElement* context) + { + (m_creator.get()->*m_setter)(type); + + if (context) + context->svgAttributeChanged(m_creator->associatedAttributeName()); + } + +private: + V8SVGDynamicPODTypeWrapper(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) + : m_creator(creator) + , m_getter(getter) + , m_setter(setter) + , m_cacheRemovalCallback(cacheRemovalCallback) + { + ASSERT(m_creator); // |creator|'s pointer was taken by m_creator. + ASSERT(getter); + ASSERT(setter); + ASSERT(cacheRemovalCallback); + } + + // Update callbacks + RefPtr<PODTypeCreator> m_creator; + GetterMethod m_getter; + SetterMethod m_setter; + CacheRemovalCallback m_cacheRemovalCallback; +}; + +// Caching facilities +template<typename PODType, typename PODTypeCreator> +struct PODTypeWrapperCacheInfo { + typedef PODType (PODTypeCreator::*GetterMethod)() const; + typedef void (PODTypeCreator::*SetterMethod)(PODType); + + // Empty value + PODTypeWrapperCacheInfo() + : creator(0) + , getter(0) + , setter(0) + , fieldHash(0) + { } + + // Deleted value + explicit PODTypeWrapperCacheInfo(WTF::HashTableDeletedValueType) + : creator(reinterpret_cast<PODTypeCreator*>(-1)) + , getter(0) + , setter(0) + , fieldHash(0) + { + } + + bool isHashTableDeletedValue() const + { + return creator == reinterpret_cast<PODTypeCreator*>(-1); + } + + PODTypeWrapperCacheInfo(PODTypeCreator* _creator, GetterMethod _getter, SetterMethod _setter, unsigned _fieldHash) + : creator(_creator) + , getter(_getter) + , setter(_setter) + , fieldHash(_fieldHash) + { + ASSERT(creator); + ASSERT(getter); + } + + bool operator==(const PODTypeWrapperCacheInfo& other) const + { + return creator == other.creator && fieldHash == other.fieldHash && getter == other.getter && setter == other.setter; + } + + PODTypeCreator* creator; + GetterMethod getter; + SetterMethod setter; + unsigned fieldHash; +}; + +template<typename PODType, typename PODTypeCreator> +struct PODTypeWrapperCacheInfoHash { + static unsigned hash(const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& info) + { + // We can't hash member function pointers, but we have enough material + // to hash the pointer and field identifier, and on a collision + // operator== will still differentiate the member function pointers. + return WTF::PairHash<void*, unsigned>::hash(std::pair<void*, unsigned>(info.creator, info.fieldHash)); + } + + static bool equal(const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& a, const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& b) + { + return a == b; + } + + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +template<typename PODType, typename PODTypeCreator> +struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits<PODTypeWrapperCacheInfo<PODType, PODTypeCreator> > { + typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; + + static const bool emptyValueIsZero = true; + static const bool needsDestruction = false; + + static const CacheInfo& emptyValue() + { + DEFINE_STATIC_LOCAL(CacheInfo, key, ()); + return key; + } + + static void constructDeletedValue(CacheInfo& slot) + { + new (&slot) CacheInfo(WTF::HashTableDeletedValue); + } + + static bool isDeletedValue(const CacheInfo& value) + { + return value.isHashTableDeletedValue(); + } +}; + +template<typename PODType, typename PODTypeCreator> +class V8SVGDynamicPODTypeWrapperCache { +public: + typedef PODType (PODTypeCreator::*GetterMethod)() const; + typedef void (PODTypeCreator::*SetterMethod)(PODType); + + typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; + typedef PODTypeWrapperCacheInfoHash<PODType, PODTypeCreator> CacheInfoHash; + typedef PODTypeWrapperCacheInfoTraits<PODType, PODTypeCreator> CacheInfoTraits; + + typedef V8SVGPODTypeWrapper<PODType> WrapperBase; + typedef V8SVGDynamicPODTypeWrapper<PODType, PODTypeCreator> DynamicWrapper; + + typedef HashMap<CacheInfo, DynamicWrapper*, CacheInfoHash, CacheInfoTraits> DynamicWrapperHashMap; + typedef typename DynamicWrapperHashMap::const_iterator DynamicWrapperHashMapIterator; + + static DynamicWrapperHashMap& dynamicWrapperHashMap() + { + DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, dynamicWrapperHashMap, ()); + return dynamicWrapperHashMap; + } + + // Used for readwrite attributes only + static PassRefPtr<WrapperBase> lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter, unsigned fieldHash) + { + DynamicWrapperHashMap& map(dynamicWrapperHashMap()); + CacheInfo info(creator, getter, setter, fieldHash); + + if (map.contains(info)) + return map.get(info); + + RefPtr<DynamicWrapper> wrapper = V8SVGDynamicPODTypeWrapper<PODType, PODTypeCreator>::create(creator, getter, setter, forgetWrapper); + map.set(info, wrapper.get()); + return wrapper.release(); + } + + static void forgetWrapper(V8SVGPODTypeWrapper<PODType>* wrapper) + { + DynamicWrapperHashMap& map(dynamicWrapperHashMap()); + + DynamicWrapperHashMapIterator it = map.begin(); + DynamicWrapperHashMapIterator end = map.end(); + + for (; it != end; ++it) { + if (it->second != wrapper) + continue; + + // It's guaranteed that there's just one object we need to take care of. + map.remove(it->first); + break; + } + } +}; + +class V8SVGPODTypeUtil { +public: + template <class P> + static P toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok); +}; + +template <class P> +P V8SVGPODTypeUtil::toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok) +{ + void *wrapper = V8DOMWrapper::convertToSVGPODTypeImpl(type, object); + if (wrapper == NULL) { + ok = false; + return P(); + } else { + ok = true; + return *static_cast<V8SVGPODTypeWrapper<P>*>(wrapper); + } +} + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // V8SVGPODTypeWrapper_h diff --git a/WebCore/bindings/v8/V8Utilities.cpp b/WebCore/bindings/v8/V8Utilities.cpp index 395a8df..c1ac6d4 100644 --- a/WebCore/bindings/v8/V8Utilities.cpp +++ b/WebCore/bindings/v8/V8Utilities.cpp @@ -58,7 +58,8 @@ void createHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> v void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) { v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); - ASSERT(cache->IsArray()); + if (!cache->IsArray()) + return; v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); for (int i = cacheArray->Length() - 1; i >= 0; --i) { v8::Local<v8::Value> cached = cacheArray->Get(v8::Integer::New(i)); @@ -67,9 +68,6 @@ void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> v return; } } - - // We should only get here if we try to remove an event listener that was never added. - ASSERT_NOT_REACHED(); } bool processingUserGesture() diff --git a/WebCore/bindings/v8/V8Utilities.h b/WebCore/bindings/v8/V8Utilities.h index fdabc7a..781d2bb 100644 --- a/WebCore/bindings/v8/V8Utilities.h +++ b/WebCore/bindings/v8/V8Utilities.h @@ -31,6 +31,7 @@ #ifndef V8Utilities_h #define V8Utilities_h +#ifdef MANUAL_MERGE_REQUIRED // FIXME: Remove once chromium dependencies on v8_utility.h are removed. #define V8UTILITIES_DEFINED 1 #if ENABLE(V8_LOCKERS) @@ -39,6 +40,8 @@ #define LOCK_V8 ((void) 0) #endif +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED #include <v8.h> namespace WebCore { @@ -80,11 +83,6 @@ namespace WebCore { static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>); static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>); static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); - - // FIXME: These NewInstance functions are here to ease upstreaming. Remove along with V8UTILITIES_DEFINED once chromium dependencies on v8_utility.h are removed. - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::Function>); - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::ObjectTemplate>); - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); }; v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function) @@ -111,22 +109,6 @@ namespace WebCore { return function->NewInstance(argc, argv); } - // FIXME: These NewInstance functions are here to ease upstreaming. Remove along with V8UTILITIES_DEFINED once chromium dependencies on v8_utility.h are removed. - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::Function> function) - { - return newInstance(function); - } - - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) - { - return newInstance(objectTemplate); - } - - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) - { - return newInstance(function, argc, argv); - } - } // namespace WebCore #endif // V8Utilities_h diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp index a21d3eb..9ed7e32 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp @@ -35,7 +35,11 @@ #include "V8WorkerContextEventListener.h" #include "Event.h" +#ifdef MANUAL_MERGE_REQUIRED #include "V8Utilities.h" +#else // MANUAL_MERGE_REQUIRED +#include "V8Binding.h" +#endif // MANUAL_MERGE_REQUIRED #include "WorkerContextExecutionProxy.h" namespace WebCore { @@ -49,7 +53,7 @@ V8WorkerContextEventListener::V8WorkerContextEventListener(WorkerContextExecutio V8WorkerContextEventListener::~V8WorkerContextEventListener() { if (m_proxy) - m_proxy->RemoveEventListener(this); + m_proxy->removeEventListener(this); disposeListenerObject(); } @@ -66,7 +70,7 @@ void V8WorkerContextEventListener::handleEvent(Event* event, bool isWindowEvent) LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = m_proxy->GetContext(); + v8::Handle<v8::Context> context = m_proxy->context(); if (context.IsEmpty()) return; @@ -74,11 +78,57 @@ void V8WorkerContextEventListener::handleEvent(Event* event, bool isWindowEvent) v8::Context::Scope scope(context); // Get the V8 wrapper for the event object. - v8::Handle<v8::Value> jsEvent = WorkerContextExecutionProxy::EventToV8Object(event); + v8::Handle<v8::Value> jsEvent = WorkerContextExecutionProxy::convertEventToV8Object(event); invokeEventHandler(context, event, jsEvent, isWindowEvent); } +bool V8WorkerContextEventListener::reportError(const String& message, const String& url, int lineNumber) +{ + // Is the EventListener disconnected? + if (disconnected()) + return false; + + // The callback function can clear the event listener and destroy 'this' object. Keep a local reference to it. + RefPtr<V8AbstractEventListener> protect(this); + + v8::HandleScope handleScope; + + v8::Handle<v8::Context> context = m_proxy->context(); + if (context.IsEmpty()) + return false; + + // Enter the V8 context in which to perform the event handling. + v8::Context::Scope scope(context); + + v8::Local<v8::Value> returnValue; + { + // Catch exceptions thrown in calling the function so they do not propagate to javascript code that caused the event to fire. + v8::TryCatch tryCatch; + tryCatch.SetVerbose(true); + + // Call the function. + if (!m_listener.IsEmpty() && m_listener->IsFunction()) { + v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener)); + v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); + + v8::Handle<v8::Value> parameters[3] = { v8String(message), v8String(url), v8::Integer::New(lineNumber) }; + returnValue = callFunction->Call(thisValue, 3, parameters); + } + + // If an error occurs while handling the script error, it should be bubbled up. + if (tryCatch.HasCaught()) { + tryCatch.Reset(); + return false; + } + } + + // If the function returns false, then the error is handled. Otherwise, the error is not handled. + bool errorHandled = returnValue->IsBoolean() && !returnValue->BooleanValue(); + + return errorHandled; +} + v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event, bool isWindowEvent) { v8::Local<v8::Function> handlerFunction = getListenerFunction(); @@ -103,7 +153,7 @@ v8::Local<v8::Object> V8WorkerContextEventListener::getReceiverObject(Event* eve return v8::Context::GetCurrent()->Global(); EventTarget* target = event->currentTarget(); - v8::Handle<v8::Value> value = WorkerContextExecutionProxy::EventTargetToV8Object(target); + v8::Handle<v8::Value> value = WorkerContextExecutionProxy::convertEventTargetToV8Object(target); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(v8::Handle<v8::Object>::Cast(value)); diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.h b/WebCore/bindings/v8/V8WorkerContextEventListener.h index 8e56a73..c901c51 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.h +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.h @@ -52,6 +52,7 @@ namespace WebCore { virtual ~V8WorkerContextEventListener(); virtual void handleEvent(Event*, bool isWindowEvent); + virtual bool reportError(const String& message, const String& url, int lineNumber); virtual bool disconnected() const { return !m_proxy; } WorkerContextExecutionProxy* proxy() const { return m_proxy; } diff --git a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp b/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp index bec25f1..ce56563 100644 --- a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp +++ b/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp @@ -43,7 +43,7 @@ static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* par V8WorkerContextObjectEventListener* listener = static_cast<V8WorkerContextObjectEventListener*>(parameter); // Remove the wrapper - listener->proxy()->RemoveEventListener(listener); + listener->proxy()->removeEventListener(listener); listener->disposeListenerObject(); } diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp index c87cdea..f80d88f 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp @@ -35,9 +35,16 @@ #include "WorkerContextExecutionProxy.h" +#include "DOMCoreException.h" +#include "DedicatedWorkerContext.h" +#include "Event.h" +#include "EventException.h" +#include "MessagePort.h" +#include "RangeException.h" #include "V8Binding.h" +#include "V8DOMMap.h" +#include "V8Index.h" #include "V8Proxy.h" -#include "Event.h" #include "V8WorkerContextEventListener.h" #include "V8WorkerContextObjectEventListener.h" #include "Worker.h" @@ -45,48 +52,17 @@ #include "WorkerLocation.h" #include "WorkerNavigator.h" #include "WorkerScriptController.h" +#include "XMLHttpRequest.h" +#include "XMLHttpRequestException.h" namespace WebCore { -static bool isWorkersEnabled = false; - static void reportFatalErrorInV8(const char* location, const char* message) { // FIXME: We temporarily deal with V8 internal error situations such as out-of-memory by crashing the worker. CRASH(); } -static void handleConsoleMessage(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) -{ - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); - if (!proxy) - return; - - WorkerContext* workerContext = proxy->workerContext(); - if (!workerContext) - return; - - v8::Handle<v8::String> errorMessageString = message->Get(); - ASSERT(!errorMessageString.IsEmpty()); - String errorMessage = ToWebCoreString(errorMessageString); - - v8::Handle<v8::Value> resourceName = message->GetScriptResourceName(); - bool useURL = (resourceName.IsEmpty() || !resourceName->IsString()); - String resourceNameString = useURL ? workerContext->url() : ToWebCoreString(resourceName); - - workerContext->addMessage(ConsoleDestination, JSMessageSource, ErrorMessageLevel, errorMessage, message->GetLineNumber(), resourceNameString); -} - -bool WorkerContextExecutionProxy::isWebWorkersEnabled() -{ - return isWorkersEnabled; -} - -void WorkerContextExecutionProxy::setIsWebWorkersEnabled(bool value) -{ - isWorkersEnabled = value; -} - WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext) : m_workerContext(workerContext) , m_recursion(0) @@ -102,8 +78,7 @@ WorkerContextExecutionProxy::~WorkerContextExecutionProxy() void WorkerContextExecutionProxy::dispose() { // Disconnect all event listeners. - if (m_listeners.get()) - { + if (m_listeners.get()) { for (V8EventListenerList::iterator iterator(m_listeners->begin()); iterator != m_listeners->end(); ++iterator) static_cast<V8WorkerContextEventListener*>(*iterator)->disconnect(); @@ -127,13 +102,16 @@ void WorkerContextExecutionProxy::dispose() WorkerContextExecutionProxy* WorkerContextExecutionProxy::retrieve() { + // Happens on frame destruction, check otherwise GetCurrent() will crash. + if (!v8::Context::InContext()) + return 0; v8::Handle<v8::Context> context = v8::Context::GetCurrent(); v8::Handle<v8::Object> global = context->Global(); - global = V8Proxy::LookupDOMWrapper(V8ClassIndex::WORKERCONTEXT, global); + global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::WORKERCONTEXT, global); // Return 0 if the current executing context is not the worker context. if (global.IsEmpty()) return 0; - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, global); + WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, global); return workerContext->script()->proxy(); } @@ -149,6 +127,7 @@ void WorkerContextExecutionProxy::initV8IfNeeded() v8::V8::IgnoreOutOfMemoryException(); v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); +#ifdef MANUAL_MERGE_REQUIRED // Set up the handler for V8 error message. v8::V8::AddMessageListener(handleConsoleMessage); @@ -156,6 +135,8 @@ void WorkerContextExecutionProxy::initV8IfNeeded() const int workerThreadPreemptionIntervalMs = 5; v8::Locker::StartPreemption(workerThreadPreemptionIntervalMs); #endif +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED v8Initialized = true; } @@ -177,7 +158,7 @@ void WorkerContextExecutionProxy::initContextIfNeeded() v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); // Create a new JS object and use it as the prototype for the shadow global object. - v8::Handle<v8::Function> workerContextConstructor = GetConstructor(V8ClassIndex::WORKERCONTEXT); + v8::Handle<v8::Function> workerContextConstructor = V8DOMWrapper::getConstructorForContext(V8ClassIndex::DEDICATEDWORKERCONTEXT, context); v8::Local<v8::Object> jsWorkerContext = SafeAllocation::newInstance(workerContextConstructor); // Bail out if allocation failed. if (jsWorkerContext.IsEmpty()) { @@ -186,9 +167,9 @@ void WorkerContextExecutionProxy::initContextIfNeeded() } // Wrap the object. - V8Proxy::SetDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(V8ClassIndex::WORKERCONTEXT), m_workerContext); + V8DOMWrapper::setDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(V8ClassIndex::DEDICATEDWORKERCONTEXT), m_workerContext); - V8Proxy::SetJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext)); + V8DOMWrapper::setJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext)); m_workerContext->ref(); // Insert the object instance as the prototype of the shadow object. @@ -198,45 +179,47 @@ void WorkerContextExecutionProxy::initContextIfNeeded() m_listeners.set(new V8EventListenerList()); } -v8::Local<v8::Function> WorkerContextExecutionProxy::GetConstructor(V8ClassIndex::V8WrapperType type) -{ - // Enter the context of the proxy to make sure that the function is - // constructed in the context corresponding to this proxy. - v8::Context::Scope scope(m_context); - v8::Handle<v8::FunctionTemplate> functionTemplate = V8Proxy::GetTemplate(type); - - // Getting the function might fail if we're running out of stack or memory. - v8::TryCatch tryCatch; - v8::Local<v8::Function> value = functionTemplate->GetFunction(); - if (value.IsEmpty()) - return v8::Local<v8::Function>(); - - return value; -} - -v8::Handle<v8::Value> WorkerContextExecutionProxy::ToV8Object(V8ClassIndex::V8WrapperType type, void* impl) +v8::Handle<v8::Value> WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl) { if (!impl) return v8::Null(); - if (type == V8ClassIndex::WORKERCONTEXT) - return WorkerContextToV8Object(static_cast<WorkerContext*>(impl)); + if (type == V8ClassIndex::DEDICATEDWORKERCONTEXT) + return convertWorkerContextToV8Object(static_cast<WorkerContext*>(impl)); + + bool isActiveDomObject = false; + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + isActiveDomObject = true; + break; +#undef MAKE_CASE + default: + break; + } - if (type == V8ClassIndex::WORKER) { + if (isActiveDomObject) { v8::Persistent<v8::Object> result = getActiveDOMObjectMap().get(impl); if (!result.IsEmpty()) return result; v8::Local<v8::Object> object = toV8(type, type, impl); - if (!object.IsEmpty()) - static_cast<Worker*>(impl)->ref(); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break; + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT_NOT_REACHED(); + } + result = v8::Persistent<v8::Object>::New(object); - V8Proxy::SetJSWrapperForDOMObject(impl, result); + V8DOMWrapper::setJSWrapperForActiveDOMObject(impl, result); return result; } // Non DOM node - v8::Persistent<v8::Object> result = domObjectMap().get(impl); + v8::Persistent<v8::Object> result = getDOMObjectMap().get(impl); if (result.IsEmpty()) { v8::Local<v8::Object> object = toV8(type, type, impl); if (!object.IsEmpty()) { @@ -247,22 +230,34 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::ToV8Object(V8ClassIndex::V8Wr case V8ClassIndex::WORKERNAVIGATOR: static_cast<WorkerNavigator*>(impl)->ref(); break; + case V8ClassIndex::DOMCOREEXCEPTION: + static_cast<DOMCoreException*>(impl)->ref(); + break; + case V8ClassIndex::RANGEEXCEPTION: + static_cast<RangeException*>(impl)->ref(); + break; + case V8ClassIndex::EVENTEXCEPTION: + static_cast<EventException*>(impl)->ref(); + break; + case V8ClassIndex::XMLHTTPREQUESTEXCEPTION: + static_cast<XMLHttpRequestException*>(impl)->ref(); + break; default: ASSERT(false); } result = v8::Persistent<v8::Object>::New(object); - V8Proxy::SetJSWrapperForDOMObject(impl, result); + V8DOMWrapper::setJSWrapperForDOMObject(impl, result); } } return result; } -v8::Handle<v8::Value> WorkerContextExecutionProxy::EventToV8Object(Event* event) +v8::Handle<v8::Value> WorkerContextExecutionProxy::convertEventToV8Object(Event* event) { if (!event) return v8::Null(); - v8::Handle<v8::Object> wrapper = domObjectMap().get(event); + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event); if (!wrapper.IsEmpty()) return wrapper; @@ -274,73 +269,79 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::EventToV8Object(Event* event) v8::Handle<v8::Object> result = toV8(type, V8ClassIndex::EVENT, event); if (result.IsEmpty()) { // Instantiation failed. Avoid updating the DOM object map and return null which - // is already handled by callers of this function in case the event is NULL. + // is already handled by callers of this function in case the event is null. return v8::Null(); } event->ref(); // fast ref - V8Proxy::SetJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result)); + V8DOMWrapper::setJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result)); return result; } -// A JS object of type EventTarget in the worker context can only be Worker or WorkerContext. -v8::Handle<v8::Value> WorkerContextExecutionProxy::EventTargetToV8Object(EventTarget* target) +v8::Handle<v8::Value> WorkerContextExecutionProxy::convertEventTargetToV8Object(EventTarget* target) { if (!target) return v8::Null(); - WorkerContext* workerContext = target->toWorkerContext(); + DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext(); if (workerContext) - return WorkerContextToV8Object(workerContext); + return convertWorkerContextToV8Object(workerContext); Worker* worker = target->toWorker(); if (worker) - return ToV8Object(V8ClassIndex::WORKER, worker); + return convertToV8Object(V8ClassIndex::WORKER, worker); + + XMLHttpRequest* xhr = target->toXMLHttpRequest(); + if (xhr) + return convertToV8Object(V8ClassIndex::XMLHTTPREQUEST, xhr); + + MessagePort* mp = target->toMessagePort(); + if (mp) + return convertToV8Object(V8ClassIndex::MESSAGEPORT, mp); ASSERT_NOT_REACHED(); return v8::Handle<v8::Value>(); } -v8::Handle<v8::Value> WorkerContextExecutionProxy::WorkerContextToV8Object(WorkerContext* workerContext) +v8::Handle<v8::Value> WorkerContextExecutionProxy::convertWorkerContextToV8Object(WorkerContext* workerContext) { if (!workerContext) return v8::Null(); - v8::Handle<v8::Context> context = workerContext->script()->proxy()->GetContext(); + v8::Handle<v8::Context> context = workerContext->script()->proxy()->context(); v8::Handle<v8::Object> global = context->Global(); ASSERT(!global.IsEmpty()); return global; } -v8::Local<v8::Object> WorkerContextExecutionProxy::toV8(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl) +v8::Local<v8::Object> WorkerContextExecutionProxy::toV8(V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl) { v8::Local<v8::Function> function; WorkerContextExecutionProxy* proxy = retrieve(); if (proxy) - function = proxy->GetConstructor(descType); + function = V8DOMWrapper::getConstructor(descriptorType, proxy->workerContext()); else - function = V8Proxy::GetTemplate(descType)->GetFunction(); + function = V8DOMWrapper::getTemplate(descriptorType)->GetFunction(); v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); - if (!instance.IsEmpty()) { + if (!instance.IsEmpty()) // Avoid setting the DOM wrapper for failed allocations. - V8Proxy::SetDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl); - } + V8DOMWrapper::setDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl); return instance; } bool WorkerContextExecutionProxy::forgetV8EventObject(Event* event) { - if (domObjectMap().contains(event)) { - domObjectMap().forget(event); + if (getDOMObjectMap().contains(event)) { + getDOMObjectMap().forget(event); return true; - } else - return false; + } + return false; } -v8::Local<v8::Value> WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, int baseLine) +ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, int baseLine, WorkerContextExecutionState* state) { LOCK_V8; v8::HandleScope hs; @@ -348,9 +349,27 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::evaluate(const String& script, initContextIfNeeded(); v8::Context::Scope scope(m_context); + v8::TryCatch exceptionCatcher; + v8::Local<v8::String> scriptString = v8ExternalString(script); - v8::Handle<v8::Script> compiledScript = V8Proxy::CompileScript(scriptString, fileName, baseLine); - return runScript(compiledScript); + v8::Handle<v8::Script> compiledScript = V8Proxy::compileScript(scriptString, fileName, baseLine); + v8::Local<v8::Value> result = runScript(compiledScript); + + if (exceptionCatcher.HasCaught()) { + v8::Local<v8::Message> message = exceptionCatcher.Message(); + state->hadException = true; + state->exception = ScriptValue(exceptionCatcher.Exception()); + state->errorMessage = toWebCoreString(message->Get()); + state->lineNumber = message->GetLineNumber(); + state->sourceURL = toWebCoreString(message->GetScriptResourceName()); + exceptionCatcher.Reset(); + } else + state->hadException = false; + + if (result.IsEmpty() || result->IsUndefined()) + return ScriptValue(); + + return ScriptValue(result); } v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Script> script) @@ -361,10 +380,10 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Scrip // Compute the source string and prevent against infinite recursion. if (m_recursion >= kMaxRecursionDepth) { v8::Local<v8::String> code = v8ExternalString("throw RangeError('Recursion too deep')"); - script = V8Proxy::CompileScript(code, "", 0); + script = V8Proxy::compileScript(code, "", 0); } - if (V8Proxy::HandleOutOfMemory()) + if (V8Proxy::handleOutOfMemory()) ASSERT(script.IsEmpty()); if (script.IsEmpty()) @@ -416,7 +435,7 @@ PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateObjectEvent return findOrCreateEventListenerHelper(object, isInline, findOnly, true); } -void WorkerContextExecutionProxy::RemoveEventListener(V8EventListener* listener) +void WorkerContextExecutionProxy::removeEventListener(V8EventListener* listener) { m_listeners->remove(listener); } diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.h b/WebCore/bindings/v8/WorkerContextExecutionProxy.h index dad191c..75024df 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.h +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.h @@ -34,9 +34,10 @@ #if ENABLE(WORKERS) -#include <v8.h> +#include "ScriptValue.h" #include "V8EventListenerList.h" #include "V8Index.h" +#include <v8.h> #include <wtf/OwnPtr.h> #include <wtf/Vector.h> @@ -48,24 +49,27 @@ namespace WebCore { class V8WorkerContextEventListener; class WorkerContext; + struct WorkerContextExecutionState { + WorkerContextExecutionState() : hadException(false), lineNumber(0) { } + + bool hadException; + ScriptValue exception; + String errorMessage; + int lineNumber; + String sourceURL; + }; + class WorkerContextExecutionProxy { public: WorkerContextExecutionProxy(WorkerContext*); ~WorkerContextExecutionProxy(); - // FIXME: following function sshould have camelCased names once V8 code-generating script is migrated. - v8::Local<v8::Context> GetContext() { return v8::Local<v8::Context>::New(m_context); } - v8::Local<v8::Function> GetConstructor(V8ClassIndex::V8WrapperType); - void RemoveEventListener(V8EventListener*); - - static v8::Handle<v8::Value> ToV8Object(V8ClassIndex::V8WrapperType type, void* impl); - static v8::Handle<v8::Value> EventToV8Object(Event* event); - static v8::Handle<v8::Value> EventTargetToV8Object(EventTarget* target); - static v8::Handle<v8::Value> WorkerContextToV8Object(WorkerContext* wc); + void removeEventListener(V8EventListener*); // Finds/creates event listener wrappers. PassRefPtr<V8EventListener> findOrCreateEventListener(v8::Local<v8::Value> listener, bool isInline, bool findOnly); PassRefPtr<V8EventListener> findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly); + PassRefPtr<V8EventListener> findOrCreateEventListenerHelper(v8::Local<v8::Value> object, bool isInline, bool findOnly, bool createObjectEventListener); // Track the event so that we can detach it from the JS wrapper when a worker // terminates. This is needed because we need to be able to dispose these @@ -73,7 +77,10 @@ namespace WebCore { void trackEvent(Event*); // Evaluate a script file in the current execution environment. - v8::Local<v8::Value> evaluate(const String& script, const String& fileName, int baseLine); + ScriptValue evaluate(const String& script, const String& fileName, int baseLine, WorkerContextExecutionState*); + + // Returns a local handle of the context. + v8::Local<v8::Context> context() { return v8::Local<v8::Context>::New(m_context); } // Returns WorkerContext object. WorkerContext* workerContext() { return m_workerContext; } @@ -81,20 +88,26 @@ namespace WebCore { // Returns WorkerContextExecutionProxy object of the currently executing context. 0 will be returned if the current executing context is not the worker context. static WorkerContextExecutionProxy* retrieve(); - // Enables HTML5 worker support. - static bool isWebWorkersEnabled(); - static void setIsWebWorkersEnabled(bool); + // We have to keep all these conversion functions here before WorkerContextExecutionProxy is refactor-ed. + template<typename T> + static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> impl) + { + return convertToV8Object(type, impl.get()); + } + static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType, void* impl); + static v8::Handle<v8::Value> convertEventToV8Object(Event*); + static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*); + static v8::Handle<v8::Value> convertWorkerContextToV8Object(WorkerContext*); private: void initV8IfNeeded(); void initContextIfNeeded(); void dispose(); - PassRefPtr<V8EventListener> findOrCreateEventListenerHelper(v8::Local<v8::Value> object, bool isInline, bool findOnly, bool createObjectEventListener); // Run an already compiled script. v8::Local<v8::Value> runScript(v8::Handle<v8::Script>); - static v8::Local<v8::Object> toV8(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl); + static v8::Local<v8::Object> toV8(V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl); static bool forgetV8EventObject(Event*); diff --git a/WebCore/bindings/v8/WorkerScriptController.cpp b/WebCore/bindings/v8/WorkerScriptController.cpp index b3ede11..f2311bf 100644 --- a/WebCore/bindings/v8/WorkerScriptController.cpp +++ b/WebCore/bindings/v8/WorkerScriptController.cpp @@ -40,6 +40,7 @@ #include "ScriptValue.h" #include "DOMTimer.h" #include "V8DOMMap.h" +#include "V8Proxy.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" #include "WorkerObjectProxy.h" @@ -61,21 +62,27 @@ WorkerScriptController::~WorkerScriptController() ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode) { + return evaluate(sourceCode, 0); +} + +ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* exception) +{ { MutexLocker lock(m_sharedDataMutex); if (m_executionForbidden) return ScriptValue(); } - v8::Local<v8::Value> result = m_proxy->evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startLine() - 1); - m_workerContext->thread()->workerObjectProxy().reportPendingActivity(m_workerContext->hasPendingActivity()); - return ScriptValue(); -} + WorkerContextExecutionState state; + ScriptValue result = m_proxy->evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startLine() - 1, &state); + if (state.hadException) { + if (exception) + *exception = state.exception; + else + m_workerContext->reportException(state.errorMessage, state.lineNumber, state.sourceURL); + } -ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* /* exception */) -{ - // FIXME: Need to return an exception. - return evaluate(sourceCode); + return result; } void WorkerScriptController::forbidExecution() @@ -85,9 +92,9 @@ void WorkerScriptController::forbidExecution() m_executionForbidden = true; } -void WorkerScriptController::setException(ScriptValue /* exception */) +void WorkerScriptController::setException(ScriptValue exception) { - notImplemented(); + throwError(*exception.v8Value()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp new file mode 100644 index 0000000..ce759eb --- /dev/null +++ b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WORKERS) + +#include "AbstractWorker.h" + +#include "ExceptionCode.h" +#include "ScriptExecutionContext.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8ObjectEventListener.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContextExecutionProxy.h" + +namespace WebCore { + +PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) +{ + if (worker->scriptExecutionContext()->isWorkerContext()) { + WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); + ASSERT(workerContextProxy); + return workerContextProxy->findOrCreateObjectEventListener(value, isAttribute, findOnly); + } + + V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext()); + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); + } + + return 0; +} + +ACCESSOR_GETTER(AbstractWorkerOnerror) +{ + INC_STATS(L"DOM.AbstractWorker.onerror._get"); + AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, info.Holder()); + if (worker->onerror()) { + V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onerror()); + v8::Local<v8::Object> v8Listener = listener->getListenerObject(); + return v8Listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(AbstractWorkerOnerror) +{ + INC_STATS(L"DOM.AbstractWorker.onerror._set"); + AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, info.Holder()); + V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onerror()); + if (value->IsNull()) { + if (oldListener) { + v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); + removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kAbstractWorkerRequestCacheIndex); + } + + // Clear the listener. + worker->setOnerror(0); + } else { + RefPtr<EventListener> listener = getEventListener(worker, value, true, false); + if (listener) { + if (oldListener) { + v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); + removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kAbstractWorkerRequestCacheIndex); + } + + worker->setOnerror(listener); + createHiddenDependency(info.Holder(), value, V8Custom::kAbstractWorkerRequestCacheIndex); + } + } +} + +CALLBACK_FUNC_DECL(AbstractWorkerAddEventListener) +{ + INC_STATS(L"DOM.AbstractWorker.addEventListener()"); + AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder()); + + RefPtr<EventListener> listener = getEventListener(worker, args[1], false, false); + if (listener) { + String type = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + worker->addEventListener(type, listener, useCapture); + + createHiddenDependency(args.Holder(), args[1], V8Custom::kAbstractWorkerRequestCacheIndex); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(AbstractWorkerRemoveEventListener) +{ + INC_STATS(L"DOM.AbstractWorker.removeEventListener()"); + AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder()); + + RefPtr<EventListener> listener = getEventListener(worker, args[1], false, true); + if (listener) { + String type = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + worker->removeEventListener(type, listener.get(), useCapture); + + removeHiddenDependency(args.Holder(), args[1], V8Custom::kAbstractWorkerRequestCacheIndex); + } + + return v8::Undefined(); +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/custom/V8AttrCustom.cpp b/WebCore/bindings/v8/custom/V8AttrCustom.cpp index f34a441..81f1586 100644 --- a/WebCore/bindings/v8/custom/V8AttrCustom.cpp +++ b/WebCore/bindings/v8/custom/V8AttrCustom.cpp @@ -42,7 +42,7 @@ namespace WebCore { ACCESSOR_SETTER(AttrValue) { - Attr* imp = V8Proxy::DOMWrapperToNode<Attr>(info.Holder()); + Attr* imp = V8DOMWrapper::convertDOMWrapperToNode<Attr>(info.Holder()); String attrValue = toWebCoreStringWithNullCheck(value); Element* ownerElement = imp->ownerElement(); diff --git a/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp index 1ad0e7a..6bd0035 100644 --- a/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp @@ -161,7 +161,7 @@ NAMED_PROPERTY_GETTER(CSSStyleDeclaration) // Search the style declaration. CSSStyleDeclaration* imp = - V8Proxy::ToNativeObject<CSSStyleDeclaration>(V8ClassIndex::CSSSTYLEDECLARATION, info.Holder()); + V8DOMWrapper::convertToNativeObject<CSSStyleDeclaration>(V8ClassIndex::CSSSTYLEDECLARATION, info.Holder()); CSSPropertyInfo* propInfo = cssPropertyInfo(name); // Do not handle non-property names. @@ -195,13 +195,13 @@ NAMED_PROPERTY_SETTER(CSSStyleDeclaration) { INC_STATS("DOM.CSSStyleDeclaration.NamedPropertySetter"); CSSStyleDeclaration* imp = - V8Proxy::ToNativeObject<CSSStyleDeclaration>( + V8DOMWrapper::convertToNativeObject<CSSStyleDeclaration>( V8ClassIndex::CSSSTYLEDECLARATION, info.Holder()); CSSPropertyInfo* propInfo = cssPropertyInfo(name); if (!propInfo) return notHandledByInterceptor(); - String propertyValue = valueToStringWithNullCheck(value); + String propertyValue = toWebCoreStringWithNullCheck(value); if (propInfo->hadPixelOrPosPrefix) propertyValue.append("px"); diff --git a/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp index 28f6b59..5fe2710 100644 --- a/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp @@ -41,7 +41,7 @@ namespace WebCore { INDEXED_PROPERTY_GETTER(CanvasPixelArray) { INC_STATS("DOM.CanvasPixelArray.IndexedPropertyGetter"); - CanvasPixelArray* pixelBuffer = V8Proxy::ToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); + CanvasPixelArray* pixelBuffer = V8DOMWrapper::convertToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); if ((index < 0) || (index >= pixelBuffer->length())) return v8::Undefined(); @@ -55,7 +55,7 @@ INDEXED_PROPERTY_GETTER(CanvasPixelArray) INDEXED_PROPERTY_SETTER(CanvasPixelArray) { INC_STATS("DOM.CanvasPixelArray.IndexedPropertySetter"); - CanvasPixelArray* pixelBuffer = V8Proxy::ToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); + CanvasPixelArray* pixelBuffer = V8DOMWrapper::convertToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); if ((index >= 0) && (index < pixelBuffer->length())) pixelBuffer->set(index, value->NumberValue()); diff --git a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp index 26086ab..676610c 100644 --- a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp @@ -43,6 +43,7 @@ #include "V8CustomBinding.h" #include "V8HTMLCanvasElement.h" #include "V8HTMLImageElement.h" +#include "V8HTMLVideoElement.h" #include "V8Proxy.h" namespace WebCore { @@ -50,10 +51,10 @@ namespace WebCore { static v8::Handle<v8::Value> toV8(CanvasStyle* style) { if (style->canvasGradient()) - return V8Proxy::ToV8Object(V8ClassIndex::CANVASGRADIENT, style->canvasGradient()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASGRADIENT, style->canvasGradient()); if (style->canvasPattern()) - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, style->canvasPattern()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASPATTERN, style->canvasPattern()); return v8String(style->color()); } @@ -64,35 +65,35 @@ static PassRefPtr<CanvasStyle> toCanvasStyle(v8::Handle<v8::Value> value) return CanvasStyle::create(toWebCoreString(value)); if (V8CanvasGradient::HasInstance(value)) - return CanvasStyle::create(V8Proxy::DOMWrapperToNative<CanvasGradient>(value)); + return CanvasStyle::create(V8DOMWrapper::convertDOMWrapperToNative<CanvasGradient>(v8::Handle<v8::Object>::Cast(value))); if (V8CanvasPattern::HasInstance(value)) - return CanvasStyle::create(V8Proxy::DOMWrapperToNative<CanvasPattern>(value)); + return CanvasStyle::create(V8DOMWrapper::convertDOMWrapperToNative<CanvasPattern>(v8::Handle<v8::Object>::Cast(value))); return 0; } ACCESSOR_GETTER(CanvasRenderingContext2DStrokeStyle) { - CanvasRenderingContext2D* impl = V8Proxy::DOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); return toV8(impl->strokeStyle()); } ACCESSOR_SETTER(CanvasRenderingContext2DStrokeStyle) { - CanvasRenderingContext2D* impl = V8Proxy::DOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); impl->setStrokeStyle(toCanvasStyle(value)); } ACCESSOR_GETTER(CanvasRenderingContext2DFillStyle) { - CanvasRenderingContext2D* impl = V8Proxy::DOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); return toV8(impl->fillStyle()); } ACCESSOR_SETTER(CanvasRenderingContext2DFillStyle) { - CanvasRenderingContext2D* impl = V8Proxy::DOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); impl->setFillStyle(toCanvasStyle(value)); } @@ -101,17 +102,17 @@ ACCESSOR_SETTER(CanvasRenderingContext2DFillStyle) CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) { INC_STATS("DOM.CanvasRenderingContext2D.setStrokeColor()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); switch (args.Length()) { case 1: if (args[0]->IsString()) - context->setStrokeColor(ToWebCoreString(args[0])); + context->setStrokeColor(toWebCoreString(args[0])); else context->setStrokeColor(toFloat(args[0])); break; case 2: if (args[0]->IsString()) - context->setStrokeColor(ToWebCoreString(args[0]), toFloat(args[1])); + context->setStrokeColor(toWebCoreString(args[0]), toFloat(args[1])); else context->setStrokeColor(toFloat(args[0]), toFloat(args[1])); break; @@ -122,7 +123,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) context->setStrokeColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "setStrokeColor: Invalid number of arguments"); + V8Proxy::throwError(V8Proxy::SyntaxError, "setStrokeColor: Invalid number of arguments"); break; } return v8::Undefined(); @@ -131,17 +132,17 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) { INC_STATS("DOM.CanvasRenderingContext2D.setFillColor()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); switch (args.Length()) { case 1: if (args[0]->IsString()) - context->setFillColor(ToWebCoreString(args[0])); + context->setFillColor(toWebCoreString(args[0])); else context->setFillColor(toFloat(args[0])); break; case 2: if (args[0]->IsString()) - context->setFillColor(ToWebCoreString(args[0]), toFloat(args[1])); + context->setFillColor(toWebCoreString(args[0]), toFloat(args[1])); else context->setFillColor(toFloat(args[0]), toFloat(args[1])); break; @@ -152,7 +153,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) context->setFillColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "setFillColor: Invalid number of arguments"); + V8Proxy::throwError(V8Proxy::SyntaxError, "setFillColor: Invalid number of arguments"); break; } return v8::Undefined(); @@ -161,13 +162,13 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeRect) { INC_STATS("DOM.CanvasRenderingContext2D.strokeRect()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); if (args.Length() == 5) context->strokeRect(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); else if (args.Length() == 4) context->strokeRect(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); else { - V8Proxy::SetDOMException(INDEX_SIZE_ERR); + V8Proxy::setDOMException(INDEX_SIZE_ERR); return notHandledByInterceptor(); } return v8::Undefined(); @@ -176,7 +177,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeRect) CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) { INC_STATS("DOM.CanvasRenderingContext2D.setShadow()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); switch (args.Length()) { case 3: @@ -184,13 +185,13 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) break; case 4: if (args[3]->IsString()) - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), ToWebCoreString(args[3])); + context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toWebCoreString(args[3])); else context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); break; case 5: if (args[3]->IsString()) - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), ToWebCoreString(args[3]), toFloat(args[4])); + context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toWebCoreString(args[3]), toFloat(args[4])); else context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); break; @@ -201,7 +202,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), toFloat(args[7])); break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "setShadow: Invalid number of arguments"); + V8Proxy::throwError(V8Proxy::SyntaxError, "setShadow: Invalid number of arguments"); break; } @@ -211,13 +212,13 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) { INC_STATS("DOM.CanvasRenderingContext2D.drawImage()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { ExceptionCode ec = 0; - HTMLImageElement* image_element = V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); + HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: context->drawImage(image_element, toFloat(args[1]), toFloat(args[2])); @@ -225,7 +226,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) case 5: context->drawImage(image_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; @@ -235,13 +236,12 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "drawImage: Invalid number of arguments"); - return v8::Undefined(); + return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); } return v8::Undefined(); } @@ -249,7 +249,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) // HTMLCanvasElement if (V8HTMLCanvasElement::HasInstance(arg)) { ExceptionCode ec = 0; - HTMLCanvasElement* canvas_element = V8Proxy::DOMWrapperToNode<HTMLCanvasElement>(arg); + HTMLCanvasElement* canvas_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: context->drawImage(canvas_element, toFloat(args[1]), toFloat(args[2])); @@ -257,7 +257,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) case 5: context->drawImage(canvas_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; @@ -267,33 +267,65 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "drawImage: Invalid number of arguments"); - return v8::Undefined(); + return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); } return v8::Undefined(); } - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); +#if ENABLE(VIDEO) + // HTMLVideoElement + if (V8HTMLVideoElement::HasInstance(arg)) { + ExceptionCode ec = 0; + HTMLVideoElement* video_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLVideoElement>(v8::Handle<v8::Object>::Cast(arg)); + switch (args.Length()) { + case 3: + context->drawImage(video_element, toFloat(args[1]), toFloat(args[2])); + break; + case 5: + context->drawImage(video_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); + if (ec != 0) { + V8Proxy::setDOMException(ec); + return notHandledByInterceptor(); + } + break; + case 9: + context->drawImage(video_element, + FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), + FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), + ec); + if (ec != 0) { + V8Proxy::setDOMException(ec); + return notHandledByInterceptor(); + } + break; + default: + return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); + } + return v8::Undefined(); + } +#endif + + V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return notHandledByInterceptor(); } CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImageFromRect) { INC_STATS("DOM.CanvasRenderingContext2D.drawImageFromRect()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* image_element = V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); - context->drawImageFromRect(image_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8]), ToWebCoreString(args[9])); + HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); + context->drawImageFromRect(image_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8]), toWebCoreString(args[9])); } else - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "drawImageFromRect: Invalid type of arguments"); + V8Proxy::throwError(V8Proxy::TypeError, "drawImageFromRect: Invalid type of arguments"); return v8::Undefined(); } @@ -301,33 +333,33 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImageFromRect) CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) { INC_STATS("DOM.CanvasRenderingContext2D.createPattern()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* image_element = V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); + HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(image_element, valueToStringWithNullCheck(args[1]), ec); + RefPtr<CanvasPattern> pattern = context->createPattern(image_element, toWebCoreStringWithNullCheck(args[1]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, pattern.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASPATTERN, pattern.release()); } if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* canvas_element = V8Proxy::DOMWrapperToNode<HTMLCanvasElement>(arg); + HTMLCanvasElement* canvas_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(v8::Handle<v8::Object>::Cast(arg)); ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(canvas_element, valueToStringWithNullCheck(args[1]), ec); + RefPtr<CanvasPattern> pattern = context->createPattern(canvas_element, toWebCoreStringWithNullCheck(args[1]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, pattern.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASPATTERN, pattern.release()); } - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return notHandledByInterceptor(); } @@ -335,17 +367,17 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DFillText) { INC_STATS("DOM.CanvasRenderingContext2D.fillText()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); // Two forms: // * fillText(text, x, y) // * fillText(text, x, y, maxWidth) if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::SetDOMException(SYNTAX_ERR); + V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } - String text = ToWebCoreString(args[0]); + String text = toWebCoreString(args[0]); float x = toFloat(args[1]); float y = toFloat(args[2]); @@ -361,17 +393,17 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DFillText) CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeText) { INC_STATS("DOM.CanvasRenderingContext2D.strokeText()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); // Two forms: // * strokeText(text, x, y) // * strokeText(text, x, y, maxWidth) if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::SetDOMException(SYNTAX_ERR); + V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } - String text = ToWebCoreString(args[0]); + String text = toWebCoreString(args[0]); float x = toFloat(args[1]); float y = toFloat(args[2]); @@ -392,20 +424,20 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DPutImageData) // * putImageData(ImageData, x, y) // * putImageData(ImageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight) if (args.Length() != 3 && args.Length() != 7) { - V8Proxy::SetDOMException(SYNTAX_ERR); + V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); ImageData* imageData = 0; // Need to check that the argument is of the correct type, since - // ToNativeObject() expects it to be correct. If the argument was incorrect + // convertToNativeObject() expects it to be correct. If the argument was incorrect // we leave it null, and putImageData() will throw the correct exception // (TYPE_MISMATCH_ERR). - if (V8Proxy::IsWrapperOfType(args[0], V8ClassIndex::IMAGEDATA)) - imageData = V8Proxy::ToNativeObject<ImageData>(V8ClassIndex::IMAGEDATA, args[0]); + if (V8DOMWrapper::isWrapperOfType(args[0], V8ClassIndex::IMAGEDATA)) + imageData = V8DOMWrapper::convertToNativeObject<ImageData>(V8ClassIndex::IMAGEDATA, v8::Handle<v8::Object>::Cast(args[0])); ExceptionCode ec = 0; @@ -415,7 +447,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DPutImageData) context->putImageData(imageData, toFloat(args[1]), toFloat(args[2]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } diff --git a/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp b/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp index e3f89b9..3c62e14 100644 --- a/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp @@ -44,12 +44,12 @@ namespace WebCore { INDEXED_PROPERTY_GETTER(ClientRectList) { INC_STATS("DOM.ClientRectList.IndexedPropertyGetter"); - ClientRectList* imp = V8Proxy::ToNativeObject<ClientRectList>(V8ClassIndex::CLIENTRECTLIST, info.Holder()); + ClientRectList* imp = V8DOMWrapper::convertToNativeObject<ClientRectList>(V8ClassIndex::CLIENTRECTLIST, info.Holder()); RefPtr<ClientRect> result = imp->item(index); if (!result) return notHandledByInterceptor(); - return V8Proxy::ToV8Object(V8ClassIndex::CLIENTRECT, result.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIENTRECT, result.release()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp b/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp index eff5511..4526304 100644 --- a/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp @@ -47,7 +47,7 @@ namespace WebCore { ACCESSOR_GETTER(ClipboardTypes) { INC_STATS("DOM.Clipboard.types()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, info.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, info.Holder()); HashSet<String> types = clipboard->types(); if (types.isEmpty()) @@ -65,7 +65,7 @@ ACCESSOR_GETTER(ClipboardTypes) CALLBACK_FUNC_DECL(ClipboardClearData) { INC_STATS("DOM.Clipboard.clearData()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); if (!args.Length()) { clipboard->clearAllData(); @@ -73,7 +73,7 @@ CALLBACK_FUNC_DECL(ClipboardClearData) } if (args.Length() != 1) - return throwError("clearData: Invalid number of arguments", V8Proxy::SYNTAX_ERROR); + return throwError("clearData: Invalid number of arguments", V8Proxy::SyntaxError); String type = toWebCoreString(args[0]); clipboard->clearData(type); @@ -83,10 +83,10 @@ CALLBACK_FUNC_DECL(ClipboardClearData) CALLBACK_FUNC_DECL(ClipboardGetData) { INC_STATS("DOM.Clipboard.getData()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); if (args.Length() != 1) - return throwError("getData: Invalid number of arguments", V8Proxy::SYNTAX_ERROR); + return throwError("getData: Invalid number of arguments", V8Proxy::SyntaxError); bool success; String result = clipboard->getData(toWebCoreString(args[0]), success); @@ -99,10 +99,10 @@ CALLBACK_FUNC_DECL(ClipboardGetData) CALLBACK_FUNC_DECL(ClipboardSetData) { INC_STATS("DOM.Clipboard.setData()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); if (args.Length() != 2) - return throwError("setData: Invalid number of arguments", V8Proxy::SYNTAX_ERROR); + return throwError("setData: Invalid number of arguments", V8Proxy::SyntaxError); String type = toWebCoreString(args[0]); String data = toWebCoreString(args[1]); @@ -112,20 +112,20 @@ CALLBACK_FUNC_DECL(ClipboardSetData) CALLBACK_FUNC_DECL(ClipboardSetDragImage) { INC_STATS("DOM.Clipboard.setDragImage()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); if (!clipboard->isForDragging()) return v8::Undefined(); if (args.Length() != 3) - return throwError("setDragImage: Invalid number of arguments", V8Proxy::SYNTAX_ERROR); + return throwError("setDragImage: Invalid number of arguments", V8Proxy::SyntaxError); int x = toInt32(args[1]); int y = toInt32(args[2]); Node* node = 0; if (V8Node::HasInstance(args[0])) - node = V8Proxy::DOMWrapperToNode<Node>(args[0]); + node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); if (!node || !node->isElementNode()) return throwError("setDragImageFromElement: Invalid first argument"); diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.cpp b/WebCore/bindings/v8/custom/V8CustomBinding.cpp index 7789797..ee45abd 100644 --- a/WebCore/bindings/v8/custom/V8CustomBinding.cpp +++ b/WebCore/bindings/v8/custom/V8CustomBinding.cpp @@ -49,9 +49,9 @@ namespace WebCore { bool allowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase* frame, String value) { - if (protocolIs(parseURL(value), "javascript")) { + if (protocolIs(deprecatedParseURL(value), "javascript")) { Node* contentDoc = frame->contentDocument(); - if (contentDoc && !V8Proxy::CheckNodeSecurity(contentDoc)) + if (contentDoc && !V8Proxy::checkNodeSecurity(contentDoc)) return false; } return true; @@ -64,6 +64,7 @@ bool allowSettingSrcToJavascriptURL(Element* element, String name, String value) return true; } +#ifdef MANUAL_MERGE_REQUIRED // DOMImplementation is a singleton in WebCore. If we use our normal // mapping from DOM objects to V8 wrappers, the same wrapper will be // shared for all frames in the same process. This is a major @@ -179,4 +180,121 @@ V8ClassIndex::V8WrapperType V8Custom::DowncastSVGPathSeg(void* pathSeg) #endif // ENABLE(SVG) +#else // MANUAL_MERGE_REQUIRED +// DOMImplementation is a singleton in WebCore. If we use our normal +// mapping from DOM objects to V8 wrappers, the same wrapper will be +// shared for all frames in the same process. This is a major +// security problem. Therefore, we generate a DOMImplementation +// wrapper per document and store it in an internal field of the +// document. Since the DOMImplementation object is a singleton, we do +// not have to do anything to keep the DOMImplementation object alive +// for the lifetime of the wrapper. +ACCESSOR_GETTER(DocumentImplementation) +{ + ASSERT(info.Holder()->InternalFieldCount() >= kDocumentMinimumInternalFieldCount); + + // Check if the internal field already contains a wrapper. + v8::Local<v8::Value> implementation = info.Holder()->GetInternalField(kDocumentImplementationIndex); + if (!implementation->IsUndefined()) + return implementation; + + // Generate a wrapper. + Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); + v8::Handle<v8::Value> wrapper = V8DOMWrapper::convertDOMImplementationToV8Object(document->implementation()); + + // Store the wrapper in the internal field. + info.Holder()->SetInternalField(kDocumentImplementationIndex, wrapper); + + return wrapper; +} + +// --------------- Security Checks ------------------------- +INDEXED_ACCESS_CHECK(History) +{ + ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); + // Only allow same origin access. + History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); + return V8Proxy::canAccessFrame(history->frame(), false); +} + +NAMED_ACCESS_CHECK(History) +{ + ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); + // Only allow same origin access. + History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); + return V8Proxy::canAccessFrame(history->frame(), false); +} + +#undef INDEXED_ACCESS_CHECK +#undef NAMED_ACCESS_CHECK +#undef NAMED_PROPERTY_GETTER +#undef NAMED_PROPERTY_SETTER + +Frame* V8Custom::GetTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data) +{ + Frame* target = 0; + switch (V8ClassIndex::FromInt(data->Int32Value())) { + case V8ClassIndex::DOMWINDOW: { + v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); + if (window.IsEmpty()) + return target; + + DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); + target = targetWindow->frame(); + break; + } + case V8ClassIndex::LOCATION: { + History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); + target = history->frame(); + break; + } + case V8ClassIndex::HISTORY: { + Location* location = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); + target = location->frame(); + break; + } + default: + break; + } + return target; +} + +#if ENABLE(SVG) +V8ClassIndex::V8WrapperType V8Custom::DowncastSVGPathSeg(void* pathSeg) +{ + WebCore::SVGPathSeg* realPathSeg = reinterpret_cast<WebCore::SVGPathSeg*>(pathSeg); + + switch (realPathSeg->pathSegType()) { +#define MAKE_CASE(svgValue, v8Value) case WebCore::SVGPathSeg::svgValue: return V8ClassIndex::v8Value + + MAKE_CASE(PATHSEG_CLOSEPATH, SVGPATHSEGCLOSEPATH); + MAKE_CASE(PATHSEG_MOVETO_ABS, SVGPATHSEGMOVETOABS); + MAKE_CASE(PATHSEG_MOVETO_REL, SVGPATHSEGMOVETOREL); + MAKE_CASE(PATHSEG_LINETO_ABS, SVGPATHSEGLINETOABS); + MAKE_CASE(PATHSEG_LINETO_REL, SVGPATHSEGLINETOREL); + MAKE_CASE(PATHSEG_CURVETO_CUBIC_ABS, SVGPATHSEGCURVETOCUBICABS); + MAKE_CASE(PATHSEG_CURVETO_CUBIC_REL, SVGPATHSEGCURVETOCUBICREL); + MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_ABS, SVGPATHSEGCURVETOQUADRATICABS); + MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_REL, SVGPATHSEGCURVETOQUADRATICREL); + MAKE_CASE(PATHSEG_ARC_ABS, SVGPATHSEGARCABS); + MAKE_CASE(PATHSEG_ARC_REL, SVGPATHSEGARCREL); + MAKE_CASE(PATHSEG_LINETO_HORIZONTAL_ABS, SVGPATHSEGLINETOHORIZONTALABS); + MAKE_CASE(PATHSEG_LINETO_HORIZONTAL_REL, SVGPATHSEGLINETOHORIZONTALREL); + MAKE_CASE(PATHSEG_LINETO_VERTICAL_ABS, SVGPATHSEGLINETOVERTICALABS); + MAKE_CASE(PATHSEG_LINETO_VERTICAL_REL, SVGPATHSEGLINETOVERTICALREL); + MAKE_CASE(PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, SVGPATHSEGCURVETOCUBICSMOOTHABS); + MAKE_CASE(PATHSEG_CURVETO_CUBIC_SMOOTH_REL, SVGPATHSEGCURVETOCUBICSMOOTHREL); + MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, SVGPATHSEGCURVETOQUADRATICSMOOTHABS); + MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, SVGPATHSEGCURVETOQUADRATICSMOOTHREL); + +#undef MAKE_CASE + + default: + return V8ClassIndex::INVALID_CLASS_INDEX; + } +} + +#endif // ENABLE(SVG) + +#endif // MANUAL_MERGE_REQUIRED } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.h b/WebCore/bindings/v8/custom/V8CustomBinding.h index e039c6f..42aca44 100644 --- a/WebCore/bindings/v8/custom/V8CustomBinding.h +++ b/WebCore/bindings/v8/custom/V8CustomBinding.h @@ -91,6 +91,7 @@ namespace WebCore { bool allowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase*, String value); bool allowSettingSrcToJavascriptURL(Element*, String name, String value); +#ifdef MANUAL_MERGE_REQUIRED class V8Custom { public: // Constants. @@ -542,6 +543,469 @@ namespace WebCore { static void WindowSetLocation(DOMWindow*, const String&); }; +#else // MANUAL_MERGE_REQUIRED + class V8Custom { + public: + // Constants. + static const int kDOMWrapperTypeIndex = 0; + static const int kDOMWrapperObjectIndex = 1; + static const int kDefaultWrapperInternalFieldCount = 2; + + static const int kNPObjectInternalFieldCount = kDefaultWrapperInternalFieldCount + 0; + + static const int kNodeEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kNodeMinimumInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kDocumentImplementationIndex = kNodeMinimumInternalFieldCount + 0; + static const int kDocumentMinimumInternalFieldCount = kNodeMinimumInternalFieldCount + 1; + + static const int kHTMLDocumentMarkerIndex = kDocumentMinimumInternalFieldCount + 0; + static const int kHTMLDocumentShadowIndex = kDocumentMinimumInternalFieldCount + 1; + static const int kHTMLDocumentInternalFieldCount = kDocumentMinimumInternalFieldCount + 2; + + static const int kXMLHttpRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kXMLHttpRequestInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kMessageChannelPort1Index = kDefaultWrapperInternalFieldCount + 0; + static const int kMessageChannelPort2Index = kDefaultWrapperInternalFieldCount + 1; + static const int kMessageChannelInternalFieldCount = kDefaultWrapperInternalFieldCount + 2; + + static const int kMessagePortRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kMessagePortEntangledPortIndex = kDefaultWrapperInternalFieldCount + 1; + static const int kMessagePortInternalFieldCount = kDefaultWrapperInternalFieldCount + 2; + +#if ENABLE(WORKERS) + static const int kWorkerRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kWorkerContextRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kWorkerContextMinimumInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kDedicatedWorkerContextRequestCacheIndex = kWorkerContextMinimumInternalFieldCount + 0; + static const int kDedicatedWorkerContextInternalFieldCount = kWorkerContextMinimumInternalFieldCount + 1; + + static const int kAbstractWorkerRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kAbstractWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; +#endif + + static const int kDOMWindowConsoleIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kDOMWindowHistoryIndex = kDefaultWrapperInternalFieldCount + 1; + static const int kDOMWindowLocationbarIndex = kDefaultWrapperInternalFieldCount + 2; + static const int kDOMWindowMenubarIndex = kDefaultWrapperInternalFieldCount + 3; + static const int kDOMWindowNavigatorIndex = kDefaultWrapperInternalFieldCount + 4; + static const int kDOMWindowPersonalbarIndex = kDefaultWrapperInternalFieldCount + 5; + static const int kDOMWindowScreenIndex = kDefaultWrapperInternalFieldCount + 6; + static const int kDOMWindowScrollbarsIndex = kDefaultWrapperInternalFieldCount + 7; + static const int kDOMWindowSelectionIndex = kDefaultWrapperInternalFieldCount + 8; + static const int kDOMWindowStatusbarIndex = kDefaultWrapperInternalFieldCount + 9; + static const int kDOMWindowToolbarIndex = kDefaultWrapperInternalFieldCount + 10; + static const int kDOMWindowLocationIndex = kDefaultWrapperInternalFieldCount + 11; + static const int kDOMWindowDOMSelectionIndex = kDefaultWrapperInternalFieldCount + 12; + static const int kDOMWindowInternalFieldCount = kDefaultWrapperInternalFieldCount + 13; + + static const int kStyleSheetOwnerNodeIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kStyleSheetInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + static const int kDOMApplicationCacheCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kDOMApplicationCacheFieldCount = kDefaultWrapperInternalFieldCount + 1; +#endif + +#define DECLARE_PROPERTY_ACCESSOR_GETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##AccessorGetter( \ + v8::Local<v8::String> name, const v8::AccessorInfo& info) + +#define DECLARE_PROPERTY_ACCESSOR_SETTER(NAME) \ + static void v8##NAME##AccessorSetter(v8::Local<v8::String> name, \ + v8::Local<v8::Value> value, const v8::AccessorInfo& info) + +#define DECLARE_PROPERTY_ACCESSOR(NAME) DECLARE_PROPERTY_ACCESSOR_GETTER(NAME); DECLARE_PROPERTY_ACCESSOR_SETTER(NAME) + +#define DECLARE_NAMED_PROPERTY_GETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##NamedPropertyGetter( \ + v8::Local<v8::String> name, const v8::AccessorInfo& info) + +#define DECLARE_NAMED_PROPERTY_SETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##NamedPropertySetter( \ + v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) + +#define DECLARE_NAMED_PROPERTY_DELETER(NAME) \ + static v8::Handle<v8::Boolean> v8##NAME##NamedPropertyDeleter( \ + v8::Local<v8::String> name, const v8::AccessorInfo& info) + +#define USE_NAMED_PROPERTY_GETTER(NAME) V8Custom::v8##NAME##NamedPropertyGetter + +#define USE_NAMED_PROPERTY_SETTER(NAME) V8Custom::v8##NAME##NamedPropertySetter + +#define USE_NAMED_PROPERTY_DELETER(NAME) V8Custom::v8##NAME##NamedPropertyDeleter + +#define DECLARE_INDEXED_PROPERTY_GETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##IndexedPropertyGetter( \ + uint32_t index, const v8::AccessorInfo& info) + +#define DECLARE_INDEXED_PROPERTY_SETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##IndexedPropertySetter( \ + uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) + +#define DECLARE_INDEXED_PROPERTY_DELETER(NAME) \ + static v8::Handle<v8::Boolean> v8##NAME##IndexedPropertyDeleter( \ + uint32_t index, const v8::AccessorInfo& info) + +#define USE_INDEXED_PROPERTY_GETTER(NAME) V8Custom::v8##NAME##IndexedPropertyGetter + +#define USE_INDEXED_PROPERTY_SETTER(NAME) V8Custom::v8##NAME##IndexedPropertySetter + +#define USE_INDEXED_PROPERTY_DELETER(NAME) V8Custom::v8##NAME##IndexedPropertyDeleter + +#define DECLARE_CALLBACK(NAME) static v8::Handle<v8::Value> v8##NAME##Callback(const v8::Arguments& args) + +#define USE_CALLBACK(NAME) V8Custom::v8##NAME##Callback + +#define DECLARE_NAMED_ACCESS_CHECK(NAME) \ + static bool v8##NAME##NamedSecurityCheck(v8::Local<v8::Object> host, \ + v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) + +#define DECLARE_INDEXED_ACCESS_CHECK(NAME) \ + static bool v8##NAME##IndexedSecurityCheck(v8::Local<v8::Object> host, \ + uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) + + DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DStrokeStyle); + DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DFillStyle); + DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowEvent); + DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowCrypto); + DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowLocation); + DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowOpener); + + DECLARE_PROPERTY_ACCESSOR(DocumentLocation); + DECLARE_PROPERTY_ACCESSOR(DocumentImplementation); + DECLARE_PROPERTY_ACCESSOR_GETTER(EventSrcElement); + DECLARE_PROPERTY_ACCESSOR(EventReturnValue); + DECLARE_PROPERTY_ACCESSOR_GETTER(EventDataTransfer); + DECLARE_PROPERTY_ACCESSOR_GETTER(EventClipboardData); + + DECLARE_PROPERTY_ACCESSOR(DOMWindowEventHandler); + DECLARE_PROPERTY_ACCESSOR(NodeEventHandler); + + DECLARE_CALLBACK(HTMLCanvasElementGetContext); + + DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLFrameElementSrc); + DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLFrameElementLocation); + DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLIFrameElementSrc); + + DECLARE_PROPERTY_ACCESSOR_SETTER(AttrValue); + + DECLARE_PROPERTY_ACCESSOR(HTMLOptionsCollectionLength); + + DECLARE_CALLBACK(HTMLInputElementSetSelectionRange); + + DECLARE_PROPERTY_ACCESSOR(HTMLInputElementSelectionStart); + DECLARE_PROPERTY_ACCESSOR(HTMLInputElementSelectionEnd); + + DECLARE_NAMED_ACCESS_CHECK(Location); + DECLARE_INDEXED_ACCESS_CHECK(History); + + DECLARE_NAMED_ACCESS_CHECK(History); + DECLARE_INDEXED_ACCESS_CHECK(Location); + + DECLARE_CALLBACK(HTMLCollectionItem); + DECLARE_CALLBACK(HTMLCollectionNamedItem); + DECLARE_CALLBACK(HTMLCollectionCallAsFunction); + + DECLARE_CALLBACK(HTMLSelectElementRemove); + + DECLARE_CALLBACK(HTMLOptionsCollectionRemove); + DECLARE_CALLBACK(HTMLOptionsCollectionAdd); + + DECLARE_CALLBACK(HTMLDocumentWrite); + DECLARE_CALLBACK(HTMLDocumentWriteln); + DECLARE_CALLBACK(HTMLDocumentOpen); + DECLARE_PROPERTY_ACCESSOR(HTMLDocumentAll); + DECLARE_NAMED_PROPERTY_GETTER(HTMLDocument); + DECLARE_NAMED_PROPERTY_DELETER(HTMLDocument); + + DECLARE_CALLBACK(DocumentEvaluate); + DECLARE_CALLBACK(DocumentGetCSSCanvasContext); + + DECLARE_CALLBACK(DOMWindowAddEventListener); + DECLARE_CALLBACK(DOMWindowRemoveEventListener); + DECLARE_CALLBACK(DOMWindowPostMessage); + DECLARE_CALLBACK(DOMWindowSetTimeout); + DECLARE_CALLBACK(DOMWindowSetInterval); + DECLARE_CALLBACK(DOMWindowAtob); + DECLARE_CALLBACK(DOMWindowBtoa); + DECLARE_CALLBACK(DOMWindowNOP); + DECLARE_CALLBACK(DOMWindowToString); + DECLARE_CALLBACK(DOMWindowShowModalDialog); + DECLARE_CALLBACK(DOMWindowOpen); + DECLARE_CALLBACK(DOMWindowClearTimeout); + DECLARE_CALLBACK(DOMWindowClearInterval); + + DECLARE_CALLBACK(DOMParserConstructor); + DECLARE_CALLBACK(HTMLAudioElementConstructor); + DECLARE_CALLBACK(HTMLImageElementConstructor); + DECLARE_CALLBACK(HTMLOptionElementConstructor); + DECLARE_CALLBACK(MessageChannelConstructor); + DECLARE_CALLBACK(WebKitCSSMatrixConstructor); + DECLARE_CALLBACK(WebKitPointConstructor); + DECLARE_CALLBACK(XMLHttpRequestConstructor); + DECLARE_CALLBACK(XMLSerializerConstructor); + DECLARE_CALLBACK(XPathEvaluatorConstructor); + DECLARE_CALLBACK(XSLTProcessorConstructor); + + DECLARE_CALLBACK(XSLTProcessorImportStylesheet); + DECLARE_CALLBACK(XSLTProcessorTransformToFragment); + DECLARE_CALLBACK(XSLTProcessorTransformToDocument); + DECLARE_CALLBACK(XSLTProcessorSetParameter); + DECLARE_CALLBACK(XSLTProcessorGetParameter); + DECLARE_CALLBACK(XSLTProcessorRemoveParameter); + + DECLARE_CALLBACK(CSSPrimitiveValueGetRGBColorValue); + + DECLARE_CALLBACK(CanvasRenderingContext2DSetStrokeColor); + DECLARE_CALLBACK(CanvasRenderingContext2DSetFillColor); + DECLARE_CALLBACK(CanvasRenderingContext2DStrokeRect); + DECLARE_CALLBACK(CanvasRenderingContext2DSetShadow); + DECLARE_CALLBACK(CanvasRenderingContext2DDrawImage); + DECLARE_CALLBACK(CanvasRenderingContext2DDrawImageFromRect); + DECLARE_CALLBACK(CanvasRenderingContext2DCreatePattern); + DECLARE_CALLBACK(CanvasRenderingContext2DFillText); + DECLARE_CALLBACK(CanvasRenderingContext2DStrokeText); + DECLARE_CALLBACK(CanvasRenderingContext2DPutImageData); + + DECLARE_PROPERTY_ACCESSOR_GETTER(ClipboardTypes); + DECLARE_CALLBACK(ClipboardClearData); + DECLARE_CALLBACK(ClipboardGetData); + DECLARE_CALLBACK(ClipboardSetData); + DECLARE_CALLBACK(ClipboardSetDragImage); + + DECLARE_CALLBACK(ElementQuerySelector); + DECLARE_CALLBACK(ElementQuerySelectorAll); + DECLARE_CALLBACK(ElementSetAttribute); + DECLARE_CALLBACK(ElementSetAttributeNode); + DECLARE_CALLBACK(ElementSetAttributeNS); + DECLARE_CALLBACK(ElementSetAttributeNodeNS); + + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationProtocol); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHost); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHostname); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationPort); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationPathname); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationSearch); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHash); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHref); + DECLARE_PROPERTY_ACCESSOR_GETTER(LocationAssign); + DECLARE_PROPERTY_ACCESSOR_GETTER(LocationReplace); + DECLARE_PROPERTY_ACCESSOR_GETTER(LocationReload); + DECLARE_CALLBACK(LocationAssign); + DECLARE_CALLBACK(LocationReplace); + DECLARE_CALLBACK(LocationReload); + DECLARE_CALLBACK(LocationToString); + DECLARE_CALLBACK(LocationValueOf); + + DECLARE_CALLBACK(NodeAddEventListener); + DECLARE_CALLBACK(NodeRemoveEventListener); + DECLARE_CALLBACK(NodeInsertBefore); + DECLARE_CALLBACK(NodeReplaceChild); + DECLARE_CALLBACK(NodeRemoveChild); + DECLARE_CALLBACK(NodeAppendChild); + + // We actually only need this because WebKit has + // navigator.appVersion as custom. Our version just + // passes through. + DECLARE_PROPERTY_ACCESSOR(NavigatorAppVersion); + + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnabort); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnerror); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnload); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnloadstart); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnprogress); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnreadystatechange); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestResponseText); + DECLARE_CALLBACK(XMLHttpRequestAddEventListener); + DECLARE_CALLBACK(XMLHttpRequestRemoveEventListener); + DECLARE_CALLBACK(XMLHttpRequestOpen); + DECLARE_CALLBACK(XMLHttpRequestSend); + DECLARE_CALLBACK(XMLHttpRequestSetRequestHeader); + DECLARE_CALLBACK(XMLHttpRequestGetResponseHeader); + DECLARE_CALLBACK(XMLHttpRequestOverrideMimeType); + DECLARE_CALLBACK(XMLHttpRequestDispatchEvent); + + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnabort); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnerror); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnload); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnloadstart); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnprogress); + DECLARE_CALLBACK(XMLHttpRequestUploadAddEventListener); + DECLARE_CALLBACK(XMLHttpRequestUploadRemoveEventListener); + DECLARE_CALLBACK(XMLHttpRequestUploadDispatchEvent); + + DECLARE_CALLBACK(TreeWalkerParentNode); + DECLARE_CALLBACK(TreeWalkerFirstChild); + DECLARE_CALLBACK(TreeWalkerLastChild); + DECLARE_CALLBACK(TreeWalkerNextNode); + DECLARE_CALLBACK(TreeWalkerPreviousNode); + DECLARE_CALLBACK(TreeWalkerNextSibling); + DECLARE_CALLBACK(TreeWalkerPreviousSibling); + + DECLARE_CALLBACK(InspectorBackendProfiles); + DECLARE_CALLBACK(InspectorBackendHighlightDOMNode); + DECLARE_CALLBACK(InspectorBackendAddResourceSourceToFrame); + DECLARE_CALLBACK(InspectorBackendAddSourceToFrame); + DECLARE_CALLBACK(InspectorBackendSearch); + DECLARE_CALLBACK(InspectorBackendSetting); + DECLARE_CALLBACK(InspectorBackendInspectedWindow); + DECLARE_CALLBACK(InspectorBackendSetSetting); + DECLARE_CALLBACK(InspectorBackendCurrentCallFrame); + DECLARE_CALLBACK(InspectorBackendDebuggerEnabled); + DECLARE_CALLBACK(InspectorBackendPauseOnExceptions); + DECLARE_CALLBACK(InspectorBackendProfilerEnabled); +#if ENABLE(DATABASE) + DECLARE_CALLBACK(InspectorBackendDatabaseTableNames); +#endif + DECLARE_CALLBACK(InspectorBackendWrapCallback); + + DECLARE_CALLBACK(NodeIteratorNextNode); + DECLARE_CALLBACK(NodeIteratorPreviousNode); + + DECLARE_CALLBACK(NodeFilterAcceptNode); + + DECLARE_CALLBACK(HTMLFormElementSubmit); + + DECLARE_NAMED_PROPERTY_GETTER(DOMWindow); + DECLARE_INDEXED_PROPERTY_GETTER(DOMWindow); + DECLARE_NAMED_ACCESS_CHECK(DOMWindow); + DECLARE_INDEXED_ACCESS_CHECK(DOMWindow); + + DECLARE_NAMED_PROPERTY_GETTER(HTMLFrameSetElement); + DECLARE_NAMED_PROPERTY_GETTER(HTMLFormElement); + DECLARE_NAMED_PROPERTY_GETTER(NodeList); + DECLARE_NAMED_PROPERTY_GETTER(NamedNodeMap); + DECLARE_NAMED_PROPERTY_GETTER(CSSStyleDeclaration); + DECLARE_NAMED_PROPERTY_SETTER(CSSStyleDeclaration); + DECLARE_NAMED_PROPERTY_GETTER(HTMLPlugInElement); + DECLARE_NAMED_PROPERTY_SETTER(HTMLPlugInElement); + DECLARE_INDEXED_PROPERTY_GETTER(HTMLPlugInElement); + DECLARE_INDEXED_PROPERTY_SETTER(HTMLPlugInElement); + + DECLARE_CALLBACK(HTMLPlugInElement); + + DECLARE_NAMED_PROPERTY_GETTER(StyleSheetList); + DECLARE_INDEXED_PROPERTY_GETTER(NamedNodeMap); + DECLARE_INDEXED_PROPERTY_GETTER(HTMLFormElement); + DECLARE_INDEXED_PROPERTY_GETTER(HTMLOptionsCollection); + DECLARE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection); + DECLARE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection); + DECLARE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection); + DECLARE_NAMED_PROPERTY_GETTER(HTMLCollection); + + DECLARE_INDEXED_PROPERTY_GETTER(CanvasPixelArray); + DECLARE_INDEXED_PROPERTY_SETTER(CanvasPixelArray); + + DECLARE_PROPERTY_ACCESSOR(MessagePortOnmessage); + DECLARE_PROPERTY_ACCESSOR(MessagePortOnclose); + DECLARE_CALLBACK(MessagePortStartConversation); + DECLARE_CALLBACK(MessagePortAddEventListener); + DECLARE_CALLBACK(MessagePortRemoveEventListener); + + DECLARE_CALLBACK(DatabaseChangeVersion); + DECLARE_CALLBACK(DatabaseTransaction); + DECLARE_CALLBACK(SQLTransactionExecuteSql); + DECLARE_CALLBACK(SQLResultSetRowListItem); + + DECLARE_INDEXED_PROPERTY_GETTER(ClientRectList); + +#if ENABLE(DATAGRID) + DECLARE_PROPERTY_ACCESSOR(HTMLDataGridElementDataSource); + DECLARE_INDEXED_PROPERTY_GETTER(DataGridColumnList); + DECLARE_NAMED_PROPERTY_GETTER(DataGridColumnList); +#endif + +#if ENABLE(DOM_STORAGE) + DECLARE_INDEXED_PROPERTY_GETTER(Storage); + DECLARE_INDEXED_PROPERTY_SETTER(Storage); + DECLARE_INDEXED_PROPERTY_DELETER(Storage); + DECLARE_NAMED_PROPERTY_GETTER(Storage); + DECLARE_NAMED_PROPERTY_SETTER(Storage); + DECLARE_NAMED_PROPERTY_DELETER(Storage); + static v8::Handle<v8::Array> v8StorageNamedPropertyEnumerator(const v8::AccessorInfo& info); +#endif + +#if ENABLE(SVG) + DECLARE_PROPERTY_ACCESSOR_GETTER(SVGLengthValue); + DECLARE_CALLBACK(SVGLengthConvertToSpecifiedUnits); + DECLARE_CALLBACK(SVGMatrixInverse); + DECLARE_CALLBACK(SVGMatrixRotateFromVector); + DECLARE_CALLBACK(SVGElementInstanceAddEventListener); + DECLARE_CALLBACK(SVGElementInstanceRemoveEventListener); +#endif + +#if ENABLE(WORKERS) + DECLARE_PROPERTY_ACCESSOR(AbstractWorkerOnerror); + DECLARE_CALLBACK(AbstractWorkerAddEventListener); + DECLARE_CALLBACK(AbstractWorkerRemoveEventListener); + + DECLARE_PROPERTY_ACCESSOR(DedicatedWorkerContextOnmessage); + + DECLARE_PROPERTY_ACCESSOR(WorkerOnmessage); + DECLARE_CALLBACK(WorkerConstructor); + + DECLARE_PROPERTY_ACCESSOR_GETTER(WorkerContextSelf); + DECLARE_PROPERTY_ACCESSOR(WorkerContextOnerror); + DECLARE_CALLBACK(WorkerContextImportScripts); + DECLARE_CALLBACK(WorkerContextSetTimeout); + DECLARE_CALLBACK(WorkerContextClearTimeout); + DECLARE_CALLBACK(WorkerContextSetInterval); + DECLARE_CALLBACK(WorkerContextClearInterval); + DECLARE_CALLBACK(WorkerContextAddEventListener); + DECLARE_CALLBACK(WorkerContextRemoveEventListener); +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + DECLARE_PROPERTY_ACCESSOR(DOMApplicationCacheEventHandler); + DECLARE_CALLBACK(DOMApplicationCacheAddEventListener); + DECLARE_CALLBACK(DOMApplicationCacheRemoveEventListener); +#endif + +#if ENABLE(SHARED_WORKERS) + DECLARE_CALLBACK(SharedWorkerConstructor); +#endif + +#undef DECLARE_INDEXED_ACCESS_CHECK +#undef DECLARE_NAMED_ACCESS_CHECK + +#undef DECLARE_PROPERTY_ACCESSOR_SETTER +#undef DECLARE_PROPERTY_ACCESSOR_GETTER +#undef DECLARE_PROPERTY_ACCESSOR + +#undef DECLARE_NAMED_PROPERTY_GETTER +#undef DECLARE_NAMED_PROPERTY_SETTER +#undef DECLARE_NAMED_PROPERTY_DELETER + +#undef DECLARE_INDEXED_PROPERTY_GETTER +#undef DECLARE_INDEXED_PROPERTY_SETTER +#undef DECLARE_INDEXED_PROPERTY_DELETER + +#undef DECLARE_CALLBACK + + // Returns the NPObject corresponding to an HTMLElement object. + static NPObject* GetHTMLPlugInElementNPObject(v8::Handle<v8::Object>); + + // Returns the owner frame pointer of a DOM wrapper object. It only works for + // these DOM objects requiring cross-domain access check. + static Frame* GetTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data); + + // Special case for downcasting SVG path segments. +#if ENABLE(SVG) + static V8ClassIndex::V8WrapperType DowncastSVGPathSeg(void* pathSeg); +#endif + + private: + static v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments&, bool singleShot); + static void ClearTimeoutImpl(const v8::Arguments&); + static void WindowSetLocation(DOMWindow*, const String&); + }; + +#endif // MANUAL_MERGE_REQUIRED } // namespace WebCore #endif // V8CustomBinding_h diff --git a/WebCore/bindings/v8/custom/V8CustomEventListener.cpp b/WebCore/bindings/v8/custom/V8CustomEventListener.cpp index bd9e307..305da8d 100644 --- a/WebCore/bindings/v8/custom/V8CustomEventListener.cpp +++ b/WebCore/bindings/v8/custom/V8CustomEventListener.cpp @@ -40,7 +40,7 @@ V8EventListener::V8EventListener(Frame* frame, v8::Local<v8::Object> listener, b { m_listener = v8::Persistent<v8::Object>::New(listener); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(EVENT_LISTENER, this, m_listener); + V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener); #endif } @@ -49,7 +49,7 @@ V8EventListener::~V8EventListener() if (m_frame) { V8Proxy* proxy = V8Proxy::retrieve(m_frame); if (proxy) - proxy->RemoveV8EventListener(this); + proxy->eventListeners()->remove(this); } disposeListenerObject(); @@ -83,7 +83,9 @@ v8::Local<v8::Value> V8EventListener::callListenerFunction(v8::Handle<v8::Value> v8::Handle<v8::Value> parameters[1] = { jsEvent }; V8Proxy* proxy = V8Proxy::retrieve(m_frame); - return proxy->CallFunction(handlerFunction, receiver, 1, parameters); + if (!proxy) + return v8::Local<v8::Value>(); + return proxy->callFunction(handlerFunction, receiver, 1, parameters); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp index daa9b34..2abdb15 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp @@ -55,15 +55,15 @@ void V8CustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLR LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return; v8::Context::Scope scope(context); v8::Handle<v8::Value> argv[] = { - V8Proxy::ToV8Object(V8ClassIndex::SQLTRANSACTION, transaction), - V8Proxy::ToV8Object(V8ClassIndex::SQLRESULTSET, resultSet) + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLTRANSACTION, transaction), + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLRESULTSET, resultSet) }; // Protect the frame until the callback returns. diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index 6c7aba2..4b84ebe 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -55,15 +55,15 @@ bool V8CustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return true; v8::Context::Scope scope(context); v8::Handle<v8::Value> argv[] = { - V8Proxy::ToV8Object(V8ClassIndex::SQLTRANSACTION, transaction), - V8Proxy::ToV8Object(V8ClassIndex::SQLERROR, error) + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLTRANSACTION, transaction), + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLERROR, error) }; // Protect the frame until the callback returns. diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp index c255483..704115e 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp @@ -56,14 +56,14 @@ void V8CustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bo LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return; v8::Context::Scope scope(context); v8::Handle<v8::Value> argv[] = { - V8Proxy::ToV8Object(V8ClassIndex::SQLTRANSACTION, transaction) + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLTRANSACTION, transaction) }; // Protect the frame until the callback returns. diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp index 8dcb0a8..f30467c 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp @@ -55,14 +55,14 @@ void V8CustomSQLTransactionErrorCallback::handleEvent(SQLError* error) LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return; v8::Context::Scope scope(context); v8::Handle<v8::Value> argv[] = { - V8Proxy::ToV8Object(V8ClassIndex::SQLERROR, error) + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLERROR, error) }; // Protect the frame until the callback returns. diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp index b2972e4..925271f 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp @@ -51,7 +51,7 @@ void V8CustomVoidCallback::handleEvent() LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return; @@ -88,7 +88,7 @@ bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8 V8Proxy* proxy = V8Proxy::retrieve(); ASSERT(proxy); - v8::Handle<v8::Value> result = proxy->CallFunction(callbackFunction, thisObject, argc, argv); + v8::Handle<v8::Value> result = proxy->callFunction(callbackFunction, thisObject, argc, argv); callbackReturnValue = !result.IsEmpty() && result->IsBoolean() && result->BooleanValue(); diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp new file mode 100644 index 0000000..3341924 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "config.h" +#include "V8CustomXPathNSResolver.h" + +#if ENABLE(XPATH) + +#include "PlatformString.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +namespace WebCore { + +PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver) +{ + return adoptRef(new V8CustomXPathNSResolver(resolver)); +} + +V8CustomXPathNSResolver::V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver) + : m_resolver(resolver) +{ +} + +V8CustomXPathNSResolver::~V8CustomXPathNSResolver() +{ +} + +String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) +{ + v8::Handle<v8::Function> lookupNamespaceURIFunc; + v8::Handle<v8::String> lookupNamespaceURIName = v8::String::New("lookupNamespaceURI"); + + // Check if the resolver has a function property named lookupNamespaceURI. + if (m_resolver->Has(lookupNamespaceURIName)) { + v8::Handle<v8::Value> lookupNamespaceURI = m_resolver->Get(lookupNamespaceURIName); + if (lookupNamespaceURI->IsFunction()) + lookupNamespaceURIFunc = v8::Handle<v8::Function>::Cast(lookupNamespaceURI); + } + + if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + logInfo(frame, "XPathNSResolver does not have a lookupNamespaceURI method.", String()); + return String(); + } + + // Catch exceptions from calling the namespace resolver. + v8::TryCatch try_catch; + try_catch.SetVerbose(true); // Print exceptions to console. + + const int argc = 1; + v8::Handle<v8::Value> argv[argc] = { v8String(prefix) }; + v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Handle<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; + + V8Proxy* proxy = V8Proxy::retrieve(); + v8::Handle<v8::Value> retval = proxy->callFunction(function, m_resolver, argc, argv); + + // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NAMESPACE_ERR. + if (try_catch.HasCaught()) + return String(); + + return toWebCoreStringWithNullCheck(retval); +} + +} // namespace WebCore + +#endif // ENABLE(XPATH) diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h new file mode 100644 index 0000000..f1dc65c --- /dev/null +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef V8CustomXPathNSResolver_h +#define V8CustomXPathNSResolver_h + +#if ENABLE(XPATH) + +#include "XPathNSResolver.h" +#include <v8.h> +#include <wtf/Forward.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class String; + +class V8CustomXPathNSResolver : public XPathNSResolver { +public: + static PassRefPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver); + + virtual ~V8CustomXPathNSResolver(); + virtual String lookupNamespaceURI(const String& prefix); + +private: + V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver); + + v8::Handle<v8::Object> m_resolver; // Handle to resolver object. +}; + +} // namespace WebCore + +#endif // ENABLE(XPATH) + +#endif // V8CustomXPathNSResolver_h diff --git a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp index 2ed1638..dd05b45 100644 --- a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -33,9 +33,10 @@ #if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "ApplicationCacheHost.h" #include "V8Binding.h" -#include "V8Document.h" #include "V8CustomBinding.h" +#include "V8Document.h" #include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" @@ -48,17 +49,10 @@ static const bool kFindOrCreate = false; static PassRefPtr<EventListener> argumentToEventListener(DOMApplicationCache* appcache, v8::Local<v8::Value> value, bool findOnly) { -#if 0 && ENABLE(WORKERS) - // FIXME: this is not tested yet - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) - return workerContextProxy->findOrCreateObjectEventListener(value, false, findOnly); -#endif - V8Proxy* proxy = V8Proxy::retrieve(appcache->scriptExecutionContext()); if (proxy) - return findOnly ? proxy->FindObjectEventListener(value, false) - : proxy->FindOrCreateObjectEventListener(value, false); + return findOnly ? proxy->objectListeners()->findWrapper(value, false) + : proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); return 0; } @@ -67,30 +61,28 @@ static v8::Local<v8::Object> eventListenerToV8Object(EventListener* listener) return (static_cast<V8ObjectEventListener*>(listener))->getListenerObject(); } -static inline String toEventType(v8::Local<v8::String> value) +static inline ApplicationCacheHost::EventID toEventID(v8::Local<v8::String> value) { String key = toWebCoreString(value); ASSERT(key.startsWith("on")); - return key.substring(2); + return DOMApplicationCache::toEventID(key.substring(2)); } // Handles appcache.onfooevent attribute getting ACCESSOR_GETTER(DOMApplicationCacheEventHandler) { INC_STATS("DOMApplicationCache.onevent_getter"); - DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); - if (EventListener* listener = appcache->getAttributeEventListener(toEventType(name))) { - return eventListenerToV8Object(listener); - } - return v8::Null(); + DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); + EventListener* listener = appcache->getAttributeEventListener(toEventID(name)); + return eventListenerToV8Object(listener); } // Handles appcache.onfooevent attribute setting ACCESSOR_SETTER(DOMApplicationCacheEventHandler) { INC_STATS("DOMApplicationCache.onevent_setter"); - DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); - String eventType = toEventType(name); + DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); + ApplicationCacheHost::EventID eventType = toEventID(name); if (EventListener* oldListener = appcache->getAttributeEventListener(eventType)) { v8::Local<v8::Object> object = eventListenerToV8Object(oldListener); @@ -111,7 +103,7 @@ ACCESSOR_SETTER(DOMApplicationCacheEventHandler) CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener) { INC_STATS("DOMApplicationCache.addEventListener()"); - DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); + DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOrCreate); if (listener) { @@ -127,7 +119,7 @@ CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener) CALLBACK_FUNC_DECL(DOMApplicationCacheRemoveEventListener) { INC_STATS("DOMApplicationCache.removeEventListener()"); - DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); + DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOnly); if (listener) { diff --git a/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp b/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp index f96b889..4af5c6e 100644 --- a/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp @@ -39,7 +39,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(DOMParserConstructor) { INC_STATS("DOM.DOMParser.Contructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::DOMPARSER, DOMParser>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::DOMPARSER, DOMParser>(args); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp index c13c3b2..7d0b9e6 100644 --- a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp @@ -64,12 +64,12 @@ v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args, if (argumentCount < 1) return v8::Undefined(); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); if (!imp->frame()) return v8::Undefined(); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->frame()->document()); @@ -124,7 +124,7 @@ static bool isAscii(const String& str) static v8::Handle<v8::Value> convertBase64(const String& str, bool encode) { if (!isAscii(str)) { - V8Proxy::SetDOMException(INVALID_CHARACTER_ERR); + V8Proxy::setDOMException(INVALID_CHARACTER_ERR); return notHandledByInterceptor(); } @@ -137,7 +137,7 @@ static v8::Handle<v8::Value> convertBase64(const String& str, bool encode) base64Encode(inputCharacters, outputCharacters); else { if (!base64Decode(inputCharacters, outputCharacters)) - return throwError("Cannot decode base64", V8Proxy::GENERAL_ERROR); + return throwError("Cannot decode base64", V8Proxy::GeneralError); } return v8String(String(outputCharacters.data(), outputCharacters.size())); @@ -161,20 +161,20 @@ ACCESSOR_GETTER(DOMWindowCrypto) ACCESSOR_SETTER(DOMWindowLocation) { - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return; - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); WindowSetLocation(imp, toWebCoreString(value)); } ACCESSOR_SETTER(DOMWindowOpener) { - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return; // Opener can be shadowed if it is in the same domain. @@ -197,9 +197,9 @@ ACCESSOR_SETTER(DOMWindowOpener) CALLBACK_FUNC_DECL(DOMWindowAddEventListener) { INC_STATS("DOM.DOMWindow.addEventListener()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); if (!imp->frame()) @@ -214,7 +214,7 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener) if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(args[1], false); + RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false); if (listener) { String eventType = toWebCoreString(args[0]); @@ -229,9 +229,9 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener) CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) { INC_STATS("DOM.DOMWindow.removeEventListener()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); if (!imp->frame()) @@ -245,7 +245,7 @@ CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindV8EventListener(args[1], false); + RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false); if (listener) { String eventType = toWebCoreString(args[0]); @@ -259,13 +259,12 @@ CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) CALLBACK_FUNC_DECL(DOMWindowPostMessage) { INC_STATS("DOM.DOMWindow.postMessage()"); - DOMWindow* window = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow(); ASSERT(source->frame()); v8::TryCatch tryCatch; - String message = toWebCoreString(args[0]); MessagePort* port = 0; String targetOrigin; @@ -275,11 +274,11 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) // or // postMessage(message, targetOrigin); if (args.Length() > 2) { - if (V8Proxy::IsWrapperOfType(args[1], V8ClassIndex::MESSAGEPORT)) - port = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args[1]); - targetOrigin = valueToStringWithNullOrUndefinedCheck(args[2]); + if (V8DOMWrapper::isWrapperOfType(args[1], V8ClassIndex::MESSAGEPORT)) + port = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, v8::Handle<v8::Object>::Cast(args[1])); + targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[2]); } else { - targetOrigin = valueToStringWithNullOrUndefinedCheck(args[1]); + targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[1]); } if (tryCatch.HasCaught()) @@ -288,7 +287,7 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) ExceptionCode ec = 0; window->postMessage(message, port, targetOrigin, source, ec); if (ec) - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Undefined(); } @@ -296,13 +295,13 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) CALLBACK_FUNC_DECL(DOMWindowAtob) { INC_STATS("DOM.DOMWindow.atob()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); if (args[0]->IsNull()) return v8String(""); @@ -314,13 +313,13 @@ CALLBACK_FUNC_DECL(DOMWindowAtob) CALLBACK_FUNC_DECL(DOMWindowBtoa) { INC_STATS("DOM.DOMWindow.btoa()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); if (args[0]->IsNull()) return v8String(""); @@ -373,11 +372,11 @@ static String eventNameFromAttributeName(const String& name) ACCESSOR_SETTER(DOMWindowEventHandler) { - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return; - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!imp->frame()) return; @@ -396,8 +395,7 @@ ACCESSOR_SETTER(DOMWindowEventHandler) if (!proxy) return; - RefPtr<EventListener> listener = - proxy->FindOrCreateV8EventListener(value, true); + RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), value, true); if (listener) imp->setAttributeEventListener(eventType, listener); } @@ -405,11 +403,11 @@ ACCESSOR_SETTER(DOMWindowEventHandler) ACCESSOR_GETTER(DOMWindowEventHandler) { - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return v8::Undefined(); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!imp->frame()) return v8::Undefined(); @@ -421,7 +419,7 @@ ACCESSOR_GETTER(DOMWindowEventHandler) String eventType = eventNameFromAttributeName(key); EventListener* listener = imp->getAttributeEventListener(eventType); - return V8Proxy::EventListenerToV8Object(listener); + return V8DOMWrapper::convertEventListenerToV8Object(listener); } static bool canShowModalDialogNow(const Frame* frame) @@ -518,7 +516,7 @@ static Frame* createWindow(Frame* callingFrame, // Set dialog arguments on the global object of the new frame. if (!dialogArgs.IsEmpty()) { - v8::Local<v8::Context> context = V8Proxy::GetContext(newFrame); + v8::Local<v8::Context> context = V8Proxy::context(newFrame); if (!context.IsEmpty()) { v8::Context::Scope scope(context); context->Global()->Set(v8::String::New("dialogArguments"), dialogArgs); @@ -544,11 +542,11 @@ static Frame* createWindow(Frame* callingFrame, CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) { INC_STATS("DOM.DOMWindow.showModalDialog()"); - DOMWindow* window = V8Proxy::ToNativeObject<DOMWindow>( + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>( V8ClassIndex::DOMWINDOW, args.Holder()); Frame* frame = window->frame(); - if (!frame || !V8Proxy::CanAccessFrame(frame, true)) + if (!frame || !V8Proxy::canAccessFrame(frame, true)) return v8::Undefined(); Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); @@ -562,9 +560,9 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) if (!canShowModalDialogNow(frame) || !allowPopUp()) return v8::Undefined(); - String url = valueToStringWithNullOrUndefinedCheck(args[0]); + String url = toWebCoreStringWithNullOrUndefinedCheck(args[0]); v8::Local<v8::Value> dialogArgs = args[1]; - String featureArgs = valueToStringWithNullOrUndefinedCheck(args[2]); + String featureArgs = toWebCoreStringWithNullOrUndefinedCheck(args[2]); const HashMap<String, String> features = parseModalDialogFeatures(featureArgs); @@ -611,7 +609,7 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) // Hold on to the context of the dialog window long enough to retrieve the // value of the return value property. - v8::Local<v8::Context> context = V8Proxy::GetContext(dialogFrame); + v8::Local<v8::Context> context = V8Proxy::context(dialogFrame); // Run the dialog. dialogFrame->page()->chrome()->runModal(); @@ -633,10 +631,10 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) CALLBACK_FUNC_DECL(DOMWindowOpen) { INC_STATS("DOM.DOMWindow.open()"); - DOMWindow* parent = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* parent = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); Frame* frame = parent->frame(); - if (!frame || !V8Proxy::CanAccessFrame(frame, true)) + if (!frame || !V8Proxy::canAccessFrame(frame, true)) return v8::Undefined(); Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); @@ -651,7 +649,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) if (!page) return v8::Undefined(); - String urlString = valueToStringWithNullOrUndefinedCheck(args[0]); + String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]); AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1])); // Because FrameTree::find() returns true for empty strings, we must check @@ -691,7 +689,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) frame->loader()->scheduleLocationChange(completedUrl, referrer, false, userGesture); } - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); } // In the case of a named frame or a new window, we'll use the @@ -700,7 +698,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) // Parse the values, and then work with a copy of the parsed values // so we can restore the values we may not want to overwrite after // we do the multiple monitor fixes. - WindowFeatures rawFeatures(valueToStringWithNullOrUndefinedCheck(args[2])); + WindowFeatures rawFeatures(toWebCoreStringWithNullOrUndefinedCheck(args[2])); WindowFeatures windowFeatures(rawFeatures); FloatRect screenRect = screenAvailableRect(page->mainFrame()->view()); @@ -751,18 +749,18 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) if (!frame) return v8::Undefined(); - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); } INDEXED_PROPERTY_GETTER(DOMWindow) { INC_STATS("DOM.DOMWindow.IndexedPropertyGetter"); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return notHandledByInterceptor(); - DOMWindow* window = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!window) return notHandledByInterceptor(); @@ -772,7 +770,7 @@ INDEXED_PROPERTY_GETTER(DOMWindow) Frame* child = frame->tree()->child(index); if (child) - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); return notHandledByInterceptor(); } @@ -782,11 +780,11 @@ NAMED_PROPERTY_GETTER(DOMWindow) { INC_STATS("DOM.DOMWindow.NamedPropertyGetter"); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return notHandledByInterceptor(); - DOMWindow* window = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!window) return notHandledByInterceptor(); @@ -799,7 +797,7 @@ NAMED_PROPERTY_GETTER(DOMWindow) AtomicString propName = v8StringToAtomicWebCoreString(name); Frame* child = frame->tree()->child(propName); if (child) - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); // Search IDL functions defined in the prototype v8::Handle<v8::Value> result = holder->GetRealNamedPropertyInPrototypeChain(name); @@ -812,9 +810,9 @@ NAMED_PROPERTY_GETTER(DOMWindow) RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); if (items->length() >= 1) { if (items->length() == 1) - return V8Proxy::NodeToV8Object(items->firstItem()); + return V8DOMWrapper::convertNodeToV8Object(items->firstItem()); else - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, items.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, items.release()); } } @@ -855,9 +853,9 @@ CALLBACK_FUNC_DECL(DOMWindowSetInterval) void V8Custom::ClearTimeoutImpl(const v8::Arguments& args) { - v8::Handle<v8::Value> holder = args.Holder(); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + v8::Handle<v8::Object> holder = args.Holder(); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return; ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->frame()->document()); int handle = toInt32(args[0]); @@ -882,11 +880,11 @@ CALLBACK_FUNC_DECL(DOMWindowClearInterval) NAMED_ACCESS_CHECK(DOMWindow) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); - v8::Handle<v8::Value> window = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); + v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); if (window.IsEmpty()) return false; // the frame is gone. - DOMWindow* targetWindow = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); + DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); ASSERT(targetWindow); @@ -902,17 +900,17 @@ NAMED_ACCESS_CHECK(DOMWindow) return true; } - return V8Proxy::CanAccessFrame(target, false); + return V8Proxy::canAccessFrame(target, false); } INDEXED_ACCESS_CHECK(DOMWindow) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); - v8::Handle<v8::Value> window = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); + v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); if (window.IsEmpty()) return false; - DOMWindow* targetWindow = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); + DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); ASSERT(targetWindow); @@ -924,7 +922,7 @@ INDEXED_ACCESS_CHECK(DOMWindow) if ((type == v8::ACCESS_GET || type == v8::ACCESS_HAS) && target->tree()->child(index)) return true; - return V8Proxy::CanAccessFrame(target, false); + return V8Proxy::canAccessFrame(target, false); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp b/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp new file mode 100644 index 0000000..1dde996 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DataGridColumnList.h" + +#include "Document.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +#if ENABLE(DATAGRID) + +namespace WebCore { + +INDEXED_PROPERTY_GETTER(DataGridColumnList) +{ + INC_STATS("DataGridColumnList.IndexedPropertyGetter"); + DataGridColumnList* imp = V8DOMWrapper::convertToNativeObject<DataGridColumnList>(V8ClassIndex::DATAGRIDCOLUMNLIST, info.Holder()); + DataGridColumn* result = imp->item(index); + if (!result) + return notHandledByInterceptor(); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DATAGRIDCOLUMN, result); +} + +NAMED_PROPERTY_GETTER(DataGridColumnList) +{ + INC_STATS("DataGridColumnList.NamedPropertyGetter"); + // Search the prototype chain first. + v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); + if (!value.IsEmpty()) + return value; + + // Then look for IDL defined properties on the object itself. + if (info.Holder()->HasRealNamedCallbackProperty(name)) + return notHandledByInterceptor(); + + // Finally, look up a column by name. + DataGridColumnList* imp = V8DOMWrapper::convertToNativeObject<DataGridColumnList>(V8ClassIndex::DATAGRIDCOLUMNLIST, info.Holder()); + DataGridColumn* result = imp->itemWithName(toWebCoreString(name)); + if (!result) + return notHandledByInterceptor(); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DATAGRIDCOLUMN, result); +} + +} // namespace WebCore + +#endif // ENABLE(DATAGRID) diff --git a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp index 6996d35..dbaa942 100644 --- a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp @@ -32,14 +32,23 @@ #if ENABLE(DATABASE) +#ifdef MANUAL_MERGE_REQUIRED #include "v8_binding.h" #include "v8_proxy.h" +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED #include "Database.h" +#ifdef MANUAL_MERGE_REQUIRED #include "V8CustomBinding.h" +#else // MANUAL_MERGE_REQUIRED +#include "V8Binding.h" +#include "V8CustomBinding.h" +#endif // MANUAL_MERGE_REQUIRED #include "V8CustomSQLTransactionCallback.h" #include "V8CustomSQLTransactionErrorCallback.h" #include "V8CustomVoidCallback.h" +#include "V8Proxy.h" namespace WebCore { @@ -53,37 +62,33 @@ CALLBACK_FUNC_DECL(DatabaseTransaction) { INC_STATS("DOM.Database.transaction()"); - if (args.Length() == 0) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Transaction callback is required."); - return v8::Undefined(); - } + if (!args.Length()) + return throwError("Transaction callback is required.", V8Proxy::SyntaxError); - if (!args[0]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Transaction callback must be of valid type."); - return v8::Undefined(); - } + if (!args[0]->IsObject()) + return throwError("Transaction callback must be of valid type."); - Database* database = V8Proxy::ToNativeObject<Database>(V8ClassIndex::DATABASE, args.Holder()); + Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, args.Holder()); - Frame* frame = V8Proxy::retrieveFrame(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return v8::Undefined(); RefPtr<V8CustomSQLTransactionCallback> callback = V8CustomSQLTransactionCallback::create(args[0], frame); RefPtr<V8CustomSQLTransactionErrorCallback> errorCallback; if (args.Length() > 1) { - if (!args[1]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Transaction error callback must be of valid type."); - return v8::Undefined(); - } + if (!args[1]->IsObject()) + return throwError("Transaction error callback must be of valid type."); + errorCallback = V8CustomSQLTransactionErrorCallback::create(args[1], frame); } RefPtr<V8CustomVoidCallback> successCallback; if (args.Length() > 2) { - if (!args[1]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Transaction success callback must be of valid type."); - return v8::Undefined(); - } + if (!args[1]->IsObject()) + return throwError("Transaction success callback must be of valid type."); + successCallback = V8CustomVoidCallback::create(args[2], frame); } diff --git a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp new file mode 100644 index 0000000..f13e45e --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WORKERS) + +#include "WorkerContextExecutionProxy.h" + +#include "DedicatedWorkerContext.h" +#include "V8Proxy.h" +#include "V8WorkerContextEventListener.h" + +namespace WebCore { + +ACCESSOR_GETTER(DedicatedWorkerContextOnmessage) +{ + INC_STATS(L"DOM.DedicatedWorkerContext.onmessage._get"); + DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, info.Holder()); + if (workerContext->onmessage()) { + V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); + v8::Local<v8::Object> v8Listener = listener->getListenerObject(); + return v8Listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(DedicatedWorkerContextOnmessage) +{ + INC_STATS(L"DOM.DedicatedWorkerContext.onmessage._set"); + DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, info.Holder()); + V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); + if (value->IsNull()) { + if (workerContext->onmessage()) { + v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); + removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kDedicatedWorkerContextRequestCacheIndex); + } + + // Clear the listener. + workerContext->setOnmessage(0); + } else { + RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), false, false); + if (listener) { + if (oldListener) { + v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); + removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kDedicatedWorkerContextRequestCacheIndex); + } + + workerContext->setOnmessage(listener); + createHiddenDependency(info.Holder(), value, V8Custom::kDedicatedWorkerContextRequestCacheIndex); + } + } +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp index 3eadce7..60fc22f 100644 --- a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp @@ -32,13 +32,13 @@ #include "Document.h" #include "ExceptionCode.h" -#include "JSXPathNSResolver.h" #include "Node.h" #include "XPathNSResolver.h" #include "XPathResult.h" #include "V8Binding.h" #include "V8CustomBinding.h" +#include "V8CustomXPathNSResolver.h" #include "V8Node.h" #include "V8Proxy.h" @@ -54,52 +54,61 @@ namespace WebCore { CALLBACK_FUNC_DECL(DocumentEvaluate) { INC_STATS("DOM.Document.evaluate()"); +#ifdef MANUAL_MERGE_REQUIRED #if ENABLE(XPATH) Document* document = V8Proxy::DOMWrapperToNode<Document>(args.Holder()); +#else // MANUAL_MERGE_REQUIRED + + RefPtr<Document> document = V8DOMWrapper::convertDOMWrapperToNode<Document>(args.Holder()); +#endif // MANUAL_MERGE_REQUIRED ExceptionCode ec = 0; String expression = toWebCoreString(args[0]); - Node* contextNode = 0; + RefPtr<Node> contextNode; if (V8Node::HasInstance(args[1])) - contextNode = V8Proxy::DOMWrapperToNode<Node>(args[1]); + contextNode = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])); - XPathNSResolver* resolver = 0; + RefPtr<XPathNSResolver> resolver; if (V8XPathNSResolver::HasInstance(args[2])) - resolver = V8Proxy::ToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, args[2]); + resolver = V8DOMWrapper::convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(args[2])); else if (args[2]->IsObject()) - resolver = new JSXPathNSResolver(args[2]->ToObject()); + resolver = V8CustomXPathNSResolver::create(args[2]->ToObject()); else if (!args[2]->IsNull() && !args[2]->IsUndefined()) return throwError(TYPE_MISMATCH_ERR); int type = toInt32(args[3]); - XPathResult* inResult = 0; + RefPtr<XPathResult> inResult; if (V8XPathResult::HasInstance(args[4])) - inResult = V8Proxy::ToNativeObject<XPathResult>(V8ClassIndex::XPATHRESULT, args[4]); + inResult = V8DOMWrapper::convertToNativeObject<XPathResult>(V8ClassIndex::XPATHRESULT, v8::Handle<v8::Object>::Cast(args[4])); v8::TryCatch exceptionCatcher; - RefPtr<XPathResult> result = document->evaluate(expression, contextNode, resolver, type, inResult, ec); + RefPtr<XPathResult> result = document->evaluate(expression, contextNode.get(), resolver.get(), type, inResult.get(), ec); if (exceptionCatcher.HasCaught()) return throwError(exceptionCatcher.Exception()); if (ec) return throwError(ec); +#ifdef MANUAL_MERGE_REQUIRED return V8Proxy::ToV8Object(V8ClassIndex::XPATHRESULT, result.get()); #else return throwError(NOT_SUPPORTED_ERR); #endif +#else // MANUAL_MERGE_REQUIRED + return V8DOMWrapper::convertToV8Object(V8ClassIndex::XPATHRESULT, result.release()); +#endif // MANUAL_MERGE_REQUIRED } CALLBACK_FUNC_DECL(DocumentGetCSSCanvasContext) { INC_STATS("DOM.Document.getCSSCanvasContext"); - v8::Handle<v8::Value> holder = args.Holder(); - Document* imp = V8Proxy::DOMWrapperToNode<Document>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Document* imp = V8DOMWrapper::convertDOMWrapperToNode<Document>(holder); String contextId = toWebCoreString(args[0]); String name = toWebCoreString(args[1]); int width = toInt32(args[2]); int height = toInt32(args[3]); CanvasRenderingContext2D* result = imp->getCSSCanvasContext(contextId, name, width, height); - return V8Proxy::ToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp index dfcacef..440bbdc 100644 --- a/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp @@ -34,17 +34,17 @@ namespace WebCore { ACCESSOR_GETTER(DocumentLocation) { - Document* document = V8Proxy::DOMWrapperToNative<Document>(info.Holder()); + Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); if (!document->frame()) return v8::Null(); DOMWindow* window = document->frame()->domWindow(); - return V8Proxy::ToV8Object(V8ClassIndex::LOCATION, window->location()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::LOCATION, window->location()); } ACCESSOR_SETTER(DocumentLocation) { - Document* document = V8Proxy::DOMWrapperToNative<Document>(info.Holder()); + Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); if (!document->frame()) return; diff --git a/WebCore/bindings/v8/custom/V8ElementCustom.cpp b/WebCore/bindings/v8/custom/V8ElementCustom.cpp index 64a9d3d..e17e0a9 100644 --- a/WebCore/bindings/v8/custom/V8ElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ElementCustom.cpp @@ -34,7 +34,6 @@ #include "Attr.h" #include "CSSHelper.h" #include "Document.h" -#include "EventListener.h" #include "ExceptionCode.h" #include "HTMLFrameElementBase.h" #include "HTMLNames.h" @@ -43,7 +42,6 @@ #include "V8Attr.h" #include "V8Binding.h" #include "V8CustomBinding.h" -#include "V8CustomEventListener.h" #include "V8Proxy.h" #include <wtf/RefPtr.h> @@ -53,7 +51,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(ElementSetAttribute) { INC_STATS("DOM.Element.setAttribute()"); - Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); String name = toWebCoreString(args[0]); String value = toWebCoreString(args[1]); @@ -74,8 +72,8 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNode) if (!V8Attr::HasInstance(args[0])) return throwError(TYPE_MISMATCH_ERR); - Attr* newAttr = V8Proxy::DOMWrapperToNode<Attr>(args[0]); - Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + Attr* newAttr = V8DOMWrapper::convertDOMWrapperToNode<Attr>(v8::Handle<v8::Object>::Cast(args[0])); + Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); if (!allowSettingSrcToJavascriptURL(element, newAttr->name(), newAttr->value())) return v8::Undefined(); @@ -85,13 +83,13 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNode) if (ec) throwError(ec); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } CALLBACK_FUNC_DECL(ElementSetAttributeNS) { INC_STATS("DOM.Element.setAttributeNS()"); - Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); String namespaceURI = toWebCoreStringWithNullCheck(args[0]); String qualifiedName = toWebCoreString(args[1]); String value = toWebCoreString(args[2]); @@ -113,8 +111,8 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNodeNS) if (!V8Attr::HasInstance(args[0])) return throwError(TYPE_MISMATCH_ERR); - Attr* newAttr = V8Proxy::DOMWrapperToNode<Attr>(args[0]); - Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + Attr* newAttr = V8DOMWrapper::convertDOMWrapperToNode<Attr>(v8::Handle<v8::Object>::Cast(args[0])); + Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); if (!allowSettingSrcToJavascriptURL(element, newAttr->name(), newAttr->value())) return v8::Undefined(); @@ -124,45 +122,7 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNodeNS) if (ec) throwError(ec); - return V8Proxy::NodeToV8Object(result.get()); -} - -static inline String toEventType(v8::Local<v8::String> value) -{ - String key = toWebCoreString(value); - ASSERT(key.startsWith("on")); - return key.substring(2); -} - -ACCESSOR_SETTER(ElementEventHandler) -{ - Node* node = V8Proxy::DOMWrapperToNode<Node>(info.Holder()); - - String eventType = toEventType(name); - - // Set handler if the value is a function. Otherwise, clear the - // event handler. - if (value->IsFunction()) { - V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); - // the document might be created using createDocument, - // which does not have a frame, use the active frame - if (!proxy) - proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext()); - if (!proxy) - return; - - if (RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(value, true)) - node->setAttributeEventListener(eventType, listener); - } else - node->clearAttributeEventListener(eventType); -} - -ACCESSOR_GETTER(ElementEventHandler) -{ - Node* node = V8Proxy::DOMWrapperToNode<Node>(info.Holder()); - - EventListener* listener = node->getAttributeEventListener(toEventType(name)); - return V8Proxy::EventListenerToV8Object(listener); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8EventCustom.cpp b/WebCore/bindings/v8/custom/V8EventCustom.cpp index 1dae845..8bac40f 100644 --- a/WebCore/bindings/v8/custom/V8EventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8EventCustom.cpp @@ -43,39 +43,39 @@ namespace WebCore { ACCESSOR_SETTER(EventReturnValue) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); event->setDefaultPrevented(!value->BooleanValue()); } ACCESSOR_GETTER(EventDataTransfer) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); if (event->isDragEvent()) - return V8Proxy::ToV8Object(V8ClassIndex::CLIPBOARD, static_cast<MouseEvent*>(event)->clipboard()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIPBOARD, static_cast<MouseEvent*>(event)->clipboard()); return v8::Undefined(); } ACCESSOR_GETTER(EventClipboardData) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); if (event->isClipboardEvent()) - return V8Proxy::ToV8Object(V8ClassIndex::CLIPBOARD, static_cast<ClipboardEvent*>(event)->clipboard()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIPBOARD, static_cast<ClipboardEvent*>(event)->clipboard()); return v8::Undefined(); } ACCESSOR_GETTER(EventSrcElement) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); - return V8Proxy::EventTargetToV8Object(event->target()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); + return V8DOMWrapper::convertEventTargetToV8Object(event->target()); } ACCESSOR_GETTER(EventReturnValue) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); return event->defaultPrevented() ? v8::False() : v8::True(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp new file mode 100644 index 0000000..6f9b761 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HTMLAudioElement.h" + +#include "Document.h" +#include "Frame.h" +#include "HTMLNames.h" + +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <wtf/RefPtr.h> + +namespace WebCore { + +CALLBACK_FUNC_DECL(HTMLAudioElementConstructor) +{ + INC_STATS("DOM.HTMLAudioElement.Contructor"); + + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function."); + + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("Audio constructor associated frame is unavailable", V8Proxy::ReferenceError); + + Document* document = frame->document(); + if (!document) + return throwError("Audio constructor associated document is unavailable", V8Proxy::ReferenceError); + + // Make sure the document is added to the DOM Node map. Otherwise, the HTMLAudioElement instance + // may end up being the only node in the map and get garbage-ccollected prematurely. + V8DOMWrapper::convertNodeToV8Object(document); + + RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(HTMLNames::audioTag, document); + if (args.Length() > 0) + audio->setSrc(toWebCoreString(args[0])); + + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), audio.get()); + audio->ref(); + V8DOMWrapper::setJSWrapperForDOMNode(audio.get(), v8::Persistent<v8::Object>::New(args.Holder())); + return args.Holder(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index cf66e39..6ba9367 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -40,12 +40,12 @@ namespace WebCore { CALLBACK_FUNC_DECL(HTMLCanvasElementGetContext) { - INC_STATS("DOM.HTMLCanvasElement.getContext"); - v8::Handle<v8::Value> holder = args.Holder(); - HTMLCanvasElement* imp = V8Proxy::DOMWrapperToNode<HTMLCanvasElement>(holder); - String contextId = ToWebCoreString(args[0]); + INC_STATS("DOM.HTMLCanvasElement.context"); + v8::Handle<v8::Object> holder = args.Holder(); + HTMLCanvasElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(holder); + String contextId = toWebCoreString(args[0]); CanvasRenderingContext2D* result = imp->getContext(contextId); - return V8Proxy::ToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp index 1436a48..7c9b40f 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp @@ -47,10 +47,10 @@ static v8::Handle<v8::Value> getNamedItems(HTMLCollection* collection, AtomicStr return v8::Handle<v8::Value>(); if (namedItems.size() == 1) - return V8Proxy::NodeToV8Object(namedItems.at(0).get()); + return V8DOMWrapper::convertNodeToV8Object(namedItems.at(0).release()); NodeList* list = new V8NamedNodesCollection(namedItems); - return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, list); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, list); } static v8::Handle<v8::Value> getItem(HTMLCollection* collection, v8::Handle<v8::Value> argument) @@ -66,7 +66,7 @@ static v8::Handle<v8::Value> getItem(HTMLCollection* collection, v8::Handle<v8:: } RefPtr<Node> result = collection->item(index->Uint32Value()); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } NAMED_PROPERTY_GETTER(HTMLCollection) @@ -84,21 +84,21 @@ NAMED_PROPERTY_GETTER(HTMLCollection) return v8::Handle<v8::Value>(); // Finally, search the DOM structure. - HTMLCollection* imp = V8Proxy::ToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, info.Holder()); + HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, info.Holder()); return getNamedItems(imp, v8StringToAtomicWebCoreString(name)); } CALLBACK_FUNC_DECL(HTMLCollectionItem) { INC_STATS("DOM.HTMLCollection.item()"); - HTMLCollection* imp = V8Proxy::ToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); return getItem(imp, args[0]); } CALLBACK_FUNC_DECL(HTMLCollectionNamedItem) { INC_STATS("DOM.HTMLCollection.namedItem()"); - HTMLCollection* imp = V8Proxy::ToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); v8::Handle<v8::Value> result = getNamedItems(imp, toWebCoreString(args[0])); if (result.IsEmpty()) @@ -113,7 +113,7 @@ CALLBACK_FUNC_DECL(HTMLCollectionCallAsFunction) if (args.Length() < 1) return v8::Undefined(); - HTMLCollection* imp = V8Proxy::ToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); if (args.Length() == 1) return getItem(imp, args[0]); @@ -128,7 +128,7 @@ CALLBACK_FUNC_DECL(HTMLCollectionCallAsFunction) Node* node = imp->namedItem(name); while (node) { if (!current) - return V8Proxy::NodeToV8Object(node); + return V8DOMWrapper::convertNodeToV8Object(node); node = imp->nextNamedItem(name); current--; diff --git a/WebCore/bindings/v8/custom/V8HTMLDataGridElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLDataGridElementCustom.cpp new file mode 100644 index 0000000..0ef4150 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8HTMLDataGridElementCustom.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HTMLDataGridElement.h" + +#include "Document.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8DataGridDataSource.h" +#include "V8Proxy.h" + +#if ENABLE(DATAGRID) + +namespace WebCore { + +ACCESSOR_GETTER(HTMLDataGridElementDataSource) +{ + INC_STATS("DOM.HTMLDataGridElement.dataSource._get"); + v8::Handle<v8::Object> holder = info.Holder(); + HTMLDataGridElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLDataGridElement>(holder); + DataGridDataSource* dataSource = imp->dataSource(); + if (dataSource && dataSource->isJSDataGridDataSource()) + return asV8DataGridDataSource(dataSource)->jsDataSource(); + return v8::Null(); +} + +ACCESSOR_SETTER(HTMLDataGridElementDataSource) +{ + INC_STATS("DOM.HTMLDataGridElement.dataSource._set"); + v8::Handle<v8::Object> holder = info.Holder(); + HTMLDataGridElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLDataGridElement>(holder); + RefPtr<DataGridDataSource> dataSource; + if (!value.IsEmpty()) { + Frame *frame = imp->document()->frame(); + dataSource = V8DataGridDataSource::create(value, frame); + } + imp->setDataSource(dataSource.get()); +} + +} // namespace WebCore + +#endif // ENABLE(DATAGRID) diff --git a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp index 34bf89c..a0c3d74 100644 --- a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp @@ -78,7 +78,7 @@ NAMED_PROPERTY_GETTER(HTMLDocument) return value; } - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(info.Holder()); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(info.Holder()); // Fast case for named elements that are not there. if (!htmlDocument->hasNamedItem(key.impl()) && !htmlDocument->hasExtraNamedItem(key.impl())) @@ -92,12 +92,12 @@ NAMED_PROPERTY_GETTER(HTMLDocument) Node* node = items->firstItem(); Frame* frame = 0; if (node->hasTagName(HTMLNames::iframeTag) && (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame())) - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); - return V8Proxy::NodeToV8Object(node); + return V8DOMWrapper::convertNodeToV8Object(node); } - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, items.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, items.release()); } // HTMLDocument ---------------------------------------------------------------- @@ -117,7 +117,7 @@ static String writeHelperGetString(const v8::Arguments& args) CALLBACK_FUNC_DECL(HTMLDocumentWrite) { INC_STATS("DOM.HTMLDocument.write()"); - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCallingContext(); ASSERT(frame); htmlDocument->write(writeHelperGetString(args), frame->document()); @@ -127,7 +127,7 @@ CALLBACK_FUNC_DECL(HTMLDocumentWrite) CALLBACK_FUNC_DECL(HTMLDocumentWriteln) { INC_STATS("DOM.HTMLDocument.writeln()"); - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCallingContext(); ASSERT(frame); htmlDocument->writeln(writeHelperGetString(args), frame->document()); @@ -137,12 +137,12 @@ CALLBACK_FUNC_DECL(HTMLDocumentWriteln) CALLBACK_FUNC_DECL(HTMLDocumentOpen) { INC_STATS("DOM.HTMLDocument.open()"); - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); if (args.Length() > 2) { if (Frame* frame = htmlDocument->frame()) { // Fetch the global object for the frame. - v8::Local<v8::Context> context = V8Proxy::GetContext(frame); + v8::Local<v8::Context> context = V8Proxy::context(frame); // Bail out if we cannot get the context. if (context.IsEmpty()) return v8::Undefined(); @@ -162,7 +162,7 @@ CALLBACK_FUNC_DECL(HTMLDocumentOpen) V8Proxy* proxy = V8Proxy::retrieve(frame); ASSERT(proxy); - v8::Local<v8::Value> result = proxy->CallFunction(v8::Local<v8::Function>::Cast(function), global, args.Length(), params); + v8::Local<v8::Value> result = proxy->callFunction(v8::Local<v8::Function>::Cast(function), global, args.Length(), params); delete[] params; return result; } @@ -179,9 +179,8 @@ ACCESSOR_GETTER(HTMLDocumentAll) INC_STATS("DOM.HTMLDocument.all._get"); v8::HandleScope scope; v8::Handle<v8::Object> holder = info.Holder(); - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(holder); - RefPtr<HTMLCollection> collection = WTF::getPtr(htmlDocument->all()); - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, WTF::getPtr(collection)); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(holder); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, htmlDocument->all()); } ACCESSOR_SETTER(HTMLDocumentAll) diff --git a/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp index 27ab7e3..1ec09f7 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp @@ -42,19 +42,19 @@ namespace WebCore { INDEXED_PROPERTY_GETTER(HTMLFormElement) { INC_STATS("DOM.HTMLFormElement.IndexedPropertyGetter"); - HTMLFormElement* form = V8Proxy::DOMWrapperToNode<HTMLFormElement>(info.Holder()); - + HTMLFormElement* form = V8DOMWrapper::convertDOMWrapperToNode<HTMLFormElement>(info.Holder()); + RefPtr<Node> formElement = form->elements()->item(index); if (!formElement) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(formElement.get()); + return V8DOMWrapper::convertNodeToV8Object(formElement.release()); } NAMED_PROPERTY_GETTER(HTMLFormElement) { INC_STATS("DOM.HTMLFormElement.NamedPropertyGetter"); - HTMLFormElement* imp = V8Proxy::DOMWrapperToNode<HTMLFormElement>(info.Holder()); + HTMLFormElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLFormElement>(info.Holder()); AtomicString v = v8StringToAtomicWebCoreString(name); // Call getNamedElements twice, first time check if it has a value @@ -74,15 +74,15 @@ NAMED_PROPERTY_GETTER(HTMLFormElement) ASSERT(!elements.isEmpty()); if (elements.size() == 1) - return V8Proxy::NodeToV8Object(elements.at(0).get()); + return V8DOMWrapper::convertNodeToV8Object(elements.at(0).release()); NodeList* collection = new V8NamedNodesCollection(elements); - return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, collection); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, collection); } - + CALLBACK_FUNC_DECL(HTMLFormElementSubmit) { INC_STATS("DOM.HTMLFormElement.submit()"); - HTMLFormElement* form = V8Proxy::DOMWrapperToNative<HTMLFormElement>(args.Holder()); + HTMLFormElement* form = V8DOMWrapper::convertDOMWrapperToNative<HTMLFormElement>(args.Holder()); form->submit(0, false, false); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp index bfc4c28..4f865dd 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp @@ -39,7 +39,7 @@ namespace WebCore { ACCESSOR_SETTER(HTMLFrameElementSrc) { - HTMLFrameElement* frame = V8Proxy::DOMWrapperToNode<HTMLFrameElement>(info.Holder()); + HTMLFrameElement* frame = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameElement>(info.Holder()); String srcValue = toWebCoreStringWithNullCheck(value); if (!allowSettingFrameSrcToJavascriptUrl(frame, srcValue)) @@ -50,7 +50,7 @@ ACCESSOR_SETTER(HTMLFrameElementSrc) ACCESSOR_SETTER(HTMLFrameElementLocation) { - HTMLFrameElement* frame = V8Proxy::DOMWrapperToNode<HTMLFrameElement>(info.Holder()); + HTMLFrameElement* frame = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameElement>(info.Holder()); String locationValue = toWebCoreStringWithNullCheck(value); if (!allowSettingFrameSrcToJavascriptUrl(frame, locationValue)) diff --git a/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp index 220af02..e8e2e72 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp @@ -47,14 +47,14 @@ namespace WebCore { NAMED_PROPERTY_GETTER(HTMLFrameSetElement) { INC_STATS("DOM.HTMLFrameSetElement.NamedPropertyGetter"); - HTMLFrameSetElement* imp = V8Proxy::DOMWrapperToNode<HTMLFrameSetElement>(info.Holder()); + HTMLFrameSetElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameSetElement>(info.Holder()); Node* frameNode = imp->children()->namedItem(v8StringToAtomicWebCoreString(name)); if (frameNode && frameNode->hasTagName(HTMLNames::frameTag)) { Document* doc = static_cast<HTMLFrameElement*>(frameNode)->contentDocument(); if (!doc) return v8::Undefined(); if (Frame* frame = doc->frame()) - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); } return notHandledByInterceptor(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp index 3739a4e..ce2c29a 100644 --- a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp @@ -39,8 +39,8 @@ namespace WebCore { ACCESSOR_SETTER(HTMLIFrameElementSrc) { - HTMLIFrameElement* iframe = V8Proxy::DOMWrapperToNode<HTMLIFrameElement>(info.Holder()); - String v = valueToStringWithNullCheck(value); + HTMLIFrameElement* iframe = V8DOMWrapper::convertDOMWrapperToNode<HTMLIFrameElement>(info.Holder()); + String v = toWebCoreStringWithNullCheck(value); if (!allowSettingFrameSrcToJavascriptUrl(iframe, v)) return; diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp index afcc29d..91ebd5f 100644 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp @@ -49,24 +49,28 @@ CALLBACK_FUNC_DECL(HTMLImageElementConstructor) if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - Document* document = V8Proxy::retrieveFrame()->document(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("Image constructor associated frame is unavailable", V8Proxy::ReferenceError); + + Document* document = frame->document(); if (!document) - return throwError("Image constructor associated document is unavailable", V8Proxy::REFERENCE_ERROR); + return throwError("Image constructor associated document is unavailable", V8Proxy::ReferenceError); // Make sure the document is added to the DOM Node map. Otherwise, the HTMLImageElement instance // may end up being the only node in the map and get garbage-ccollected prematurely. - V8Proxy::NodeToV8Object(document); + V8DOMWrapper::convertNodeToV8Object(document); - RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, V8Proxy::retrieveFrame()->document()); + RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, document); if (args.Length() > 0) { image->setWidth(toInt32(args[0])); if (args.Length() > 1) image->setHeight(toInt32(args[1])); } - V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), image.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), image.get()); image->ref(); - V8Proxy::SetJSWrapperForDOMNode(image.get(), v8::Persistent<v8::Object>::New(args.Holder())); + V8DOMWrapper::setJSWrapperForDOMNode(image.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp index 628634d..63fbcec 100644 --- a/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp @@ -41,7 +41,7 @@ ACCESSOR_GETTER(HTMLInputElementSelectionStart) { INC_STATS("DOM.HTMLInputElement.selectionStart._get"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) return throwError("Accessing selectionStart on an input element that cannot have a selection."); @@ -54,7 +54,7 @@ ACCESSOR_SETTER(HTMLInputElementSelectionStart) { INC_STATS("DOM.HTMLInputElement.selectionStart._set"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) { throwError("Accessing selectionStart on an input element that cannot have a selection."); @@ -67,7 +67,7 @@ ACCESSOR_GETTER(HTMLInputElementSelectionEnd) { INC_STATS("DOM.HTMLInputElement.selectionEnd._get"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) return throwError("Accessing selectionEnd on an input element that cannot have a selection."); @@ -80,7 +80,7 @@ ACCESSOR_SETTER(HTMLInputElementSelectionEnd) { INC_STATS("DOM.HTMLInputElement.selectionEnd._set"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) { throwError("Accessing selectionEnd on an input element that cannot have a selection."); @@ -94,7 +94,7 @@ CALLBACK_FUNC_DECL(HTMLInputElementSetSelectionRange) { INC_STATS("DOM.HTMLInputElement.setSelectionRange"); v8::Handle<v8::Object> holder = args.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) return throwError("Calling setSelectionRange on an input element that cannot have a selection."); diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp index 93a9b68..c22d127 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp @@ -50,11 +50,15 @@ CALLBACK_FUNC_DECL(HTMLOptionElementConstructor) if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - Document* document = V8Proxy::retrieveFrame()->document(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("Option constructor associated frame is unavailable", V8Proxy::ReferenceError); + + Document* document = frame->document(); if (!document) - return throwError("Option constructor associated document is unavailable", V8Proxy::REFERENCE_ERROR); + return throwError("Option constructor associated document is unavailable", V8Proxy::ReferenceError); - RefPtr<HTMLOptionElement> option = new HTMLOptionElement(HTMLNames::optionTag, V8Proxy::retrieveFrame()->document()); + RefPtr<HTMLOptionElement> option = new HTMLOptionElement(HTMLNames::optionTag, document); ExceptionCode ec = 0; RefPtr<Text> text = document->createTextNode(""); @@ -81,9 +85,9 @@ CALLBACK_FUNC_DECL(HTMLOptionElementConstructor) } } - V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), option.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), option.get()); option->ref(); - V8Proxy::SetJSWrapperForDOMNode(option.get(), v8::Persistent<v8::Object>::New(args.Holder())); + V8DOMWrapper::setJSWrapperForDOMNode(option.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp index 9f0d25e..02c3499 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp @@ -46,7 +46,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(HTMLOptionsCollectionRemove) { INC_STATS("DOM.HTMLOptionsCollection.remove()"); - HTMLOptionsCollection* imp = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); + HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); HTMLSelectElement* base = static_cast<HTMLSelectElement*>(imp->base()); return removeElement(base, args); } @@ -55,11 +55,11 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) { INC_STATS("DOM.HTMLOptionsCollection.add()"); if (!V8HTMLOptionElement::HasInstance(args[0])) { - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return v8::Undefined(); } - HTMLOptionsCollection* imp = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); - HTMLOptionElement* option = V8Proxy::DOMWrapperToNode<HTMLOptionElement>(args[0]); + HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); + HTMLOptionElement* option = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>(v8::Handle<v8::Object>::Cast(args[0]))); ExceptionCode ec = 0; if (args.Length() < 2) @@ -67,7 +67,7 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) else { bool ok; v8::TryCatch try_catch; - int index = ToInt32(args[1], ok); + int index = toInt32(args[1], ok); if (try_catch.HasCaught()) return v8::Undefined(); @@ -79,7 +79,7 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) } if (ec != 0) - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Undefined(); } @@ -87,7 +87,7 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) ACCESSOR_GETTER(HTMLOptionsCollectionLength) { INC_STATS("DOM.HTMLOptionsCollection.length._get"); - HTMLOptionsCollection* imp = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); int v = imp->length(); return v8::Integer::New(v); } @@ -95,7 +95,7 @@ ACCESSOR_GETTER(HTMLOptionsCollectionLength) ACCESSOR_SETTER(HTMLOptionsCollectionLength) { INC_STATS("DOM.HTMLOptionsCollection.length._set"); - HTMLOptionsCollection* imp = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); double v = value->NumberValue(); unsigned newLength = 0; ExceptionCode ec = 0; @@ -110,25 +110,25 @@ ACCESSOR_SETTER(HTMLOptionsCollectionLength) if (!ec) imp->setLength(value->Uint32Value(), ec); - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); } INDEXED_PROPERTY_GETTER(HTMLOptionsCollection) { INC_STATS("DOM.HTMLOptionsCollection.IndexedPropertyGetter"); - HTMLOptionsCollection* collection = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* collection = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); RefPtr<Node> result = collection->item(index); if (!result) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } INDEXED_PROPERTY_SETTER(HTMLOptionsCollection) { INC_STATS("DOM.HTMLOptionsCollection.IndexedPropertySetter"); - HTMLOptionsCollection* collection = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* collection = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); HTMLSelectElement* base = static_cast<HTMLSelectElement*>(collection->base()); return toOptionsCollectionSetter(index, value, base); } diff --git a/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp index a6e41a1..13c82f3 100644 --- a/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp @@ -35,17 +35,15 @@ #include "V8Binding.h" #include "V8CustomBinding.h" +#include "V8NPObject.h" #include "V8Proxy.h" -// FIXME: The name of this file will change once refactoring is complete -#include "v8_npobject.h" - namespace WebCore { NAMED_PROPERTY_GETTER(HTMLPlugInElement) { INC_STATS("DOM.HTMLPlugInElement.NamedPropertyGetter"); - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -54,13 +52,13 @@ NAMED_PROPERTY_GETTER(HTMLPlugInElement) if (instance.IsEmpty()) return notHandledByInterceptor(); - return NPObjectGetNamedProperty(instance, name); + return npObjectGetNamedProperty(instance, name); } NAMED_PROPERTY_SETTER(HTMLPlugInElement) { INC_STATS("DOM.HTMLPlugInElement.NamedPropertySetter"); - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -69,19 +67,19 @@ NAMED_PROPERTY_SETTER(HTMLPlugInElement) if (instance.IsEmpty()) return notHandledByInterceptor(); - return NPObjectSetNamedProperty(instance, name, value); + return npObjectSetNamedProperty(instance, name, value); } CALLBACK_FUNC_DECL(HTMLPlugInElement) { INC_STATS("DOM.HTMLPluginElement()"); - return NPObjectInvokeDefaultHandler(args); + return npObjectInvokeDefaultHandler(args); } INDEXED_PROPERTY_GETTER(HTMLPlugInElement) { INC_STATS("DOM.HTMLPlugInElement.IndexedPropertyGetter"); - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -90,13 +88,13 @@ INDEXED_PROPERTY_GETTER(HTMLPlugInElement) if (instance.IsEmpty()) return notHandledByInterceptor(); - return NPObjectGetIndexedProperty(instance, index); + return npObjectGetIndexedProperty(instance, index); } INDEXED_PROPERTY_SETTER(HTMLPlugInElement) { INC_STATS("DOM.HTMLPlugInElement.IndexedPropertySetter"); - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -105,7 +103,7 @@ INDEXED_PROPERTY_SETTER(HTMLPlugInElement) if (instance.IsEmpty()) return notHandledByInterceptor(); - return NPObjectSetIndexedProperty(instance, index, value); + return npObjectSetIndexedProperty(instance, index, value); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp index 8b3b72a..0dfa515 100644 --- a/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp @@ -43,7 +43,7 @@ namespace WebCore { NAMED_PROPERTY_GETTER(HTMLSelectElementCollection) { INC_STATS("DOM.HTMLSelectElementCollection.NamedPropertySetter"); - HTMLSelectElement* select = V8Proxy::DOMWrapperToNode<HTMLSelectElement>(info.Holder()); + HTMLSelectElement* select = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(info.Holder()); v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); if (!value.IsEmpty()) @@ -62,16 +62,16 @@ NAMED_PROPERTY_GETTER(HTMLSelectElementCollection) return notHandledByInterceptor(); if (items.size() == 1) - return V8Proxy::NodeToV8Object(items.at(0).get()); + return V8DOMWrapper::convertNodeToV8Object(items.at(0).release()); NodeList* list = new V8NamedNodesCollection(items); - return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, list); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, list); } INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection) { INC_STATS("DOM.HTMLSelectElementCollection.IndexedPropertySetter"); - HTMLSelectElement* select = V8Proxy::DOMWrapperToNode<HTMLSelectElement>(info.Holder()); + HTMLSelectElement* select = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(info.Holder()); return toOptionsCollectionSetter(index, value, select); } diff --git a/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp index 97f7726..661ffa2 100644 --- a/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp @@ -44,19 +44,19 @@ namespace WebCore { CALLBACK_FUNC_DECL(HTMLSelectElementRemove) { INC_STATS("DOM.HTMLSelectElement.remove"); - HTMLSelectElement* imp = V8Proxy::DOMWrapperToNode<HTMLSelectElement>(args.Holder()); + HTMLSelectElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(args.Holder()); return removeElement(imp, args); } v8::Handle<v8::Value> removeElement(HTMLSelectElement* imp, const v8::Arguments& args) { if (V8HTMLOptionElement::HasInstance(args[0])) { - HTMLOptionElement* element = V8Proxy::DOMWrapperToNode<HTMLOptionElement>(args[0]); + HTMLOptionElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>::Cast(args[0])); imp->remove(element->index()); return v8::Undefined(); } - imp->remove(ToInt32(args[0])); + imp->remove(toInt32(args[0])); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8InspectorControllerCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp index a85c0d6..2571df4 100644 --- a/WebCore/bindings/v8/custom/V8InspectorControllerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp @@ -29,12 +29,13 @@ */ #include "config.h" -#include "InspectorController.h" +#include "InspectorBackend.h" #include "DOMWindow.h" #include "Frame.h" #include "FrameLoader.h" #include "ExceptionCode.h" +#include "InspectorController.h" #include "InspectorResource.h" #include "NotImplemented.h" #include "Node.h" @@ -49,58 +50,31 @@ namespace WebCore { -CALLBACK_FUNC_DECL(InspectorControllerHighlightDOMNode) +CALLBACK_FUNC_DECL(InspectorBackendHighlightDOMNode) { - INC_STATS("InspectorController.highlightDOMNode()"); + INC_STATS("InspectorBackend.highlightDOMNode()"); if (args.Length() < 1) return v8::Undefined(); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args[0]); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); if (!node) return v8::Undefined(); - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - inspectorController->highlight(node); + InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); + inspectorBackend->highlight(node); return v8::Undefined(); } -CALLBACK_FUNC_DECL(InspectorControllerGetResourceDocumentNode) +CALLBACK_FUNC_DECL(InspectorBackendSearch) { - INC_STATS("InspectorController.getResourceDocumentNode()"); - - if (args.Length() < 1) - return v8::Undefined(); - - if (!args[1]->IsNumber()) - return v8::Undefined(); - - unsigned identifier = args[1]->Int32Value(); - - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - RefPtr<InspectorResource> resource = inspectorController->resources().get(identifier); - ASSERT(resource); - if (!resource) - return v8::Undefined(); - - Frame* frame = resource->frame(); - Document* document = frame->document(); - - if (document->isPluginDocument() || document->isImageDocument() || document->isMediaDocument()) - return v8::Undefined(); - - return V8Proxy::ToV8Object(V8ClassIndex::DOCUMENT, document); -} - -CALLBACK_FUNC_DECL(InspectorControllerSearch) -{ - INC_STATS("InspectorController.search()"); + INC_STATS("InspectorBackend.search()"); if (args.Length() < 2) return v8::Undefined(); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args[0]); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); if (!node) return v8::Undefined(); @@ -124,7 +98,7 @@ CALLBACK_FUNC_DECL(InspectorControllerSearch) if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) break; - result->Set(v8::Number::New(index++), V8Proxy::ToV8Object<Range>(V8ClassIndex::RANGE, resultRange.get())); + result->Set(v8::Number::New(index++), V8DOMWrapper::convertToV8Object(V8ClassIndex::RANGE, resultRange.release())); setStart(searchRange.get(), newStart); } while (true); @@ -133,25 +107,28 @@ CALLBACK_FUNC_DECL(InspectorControllerSearch) } #if ENABLE(DATABASE) -CALLBACK_FUNC_DECL(InspectorControllerDatabaseTableNames) +CALLBACK_FUNC_DECL(InspectorBackendDatabaseTableNames) { - INC_STATS("InspectorController.databaseTableNames()"); + INC_STATS("InspectorBackend.databaseTableNames()"); v8::Local<v8::Array> result = v8::Array::New(0); return result; } #endif -CALLBACK_FUNC_DECL(InspectorControllerInspectedWindow) +CALLBACK_FUNC_DECL(InspectorBackendInspectedWindow) { - INC_STATS("InspectorController.inspectedWindow()"); + INC_STATS("InspectorBackend.inspectedWindow()"); - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - return V8Proxy::ToV8Object<DOMWindow>(V8ClassIndex::DOMWINDOW, inspectorController->inspectedPage()->mainFrame()->domWindow()); + InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); + InspectorController* ic = inspectorBackend->inspectorController(); + if (!ic) + return v8::Undefined(); + return V8DOMWrapper::convertToV8Object<DOMWindow>(V8ClassIndex::DOMWINDOW, ic->inspectedPage()->mainFrame()->domWindow()); } -CALLBACK_FUNC_DECL(InspectorControllerSetting) +CALLBACK_FUNC_DECL(InspectorBackendSetting) { - INC_STATS("InspectorController.setting()"); + INC_STATS("InspectorBackend.setting()"); if (args.Length() < 1) return v8::Undefined(); @@ -160,8 +137,11 @@ CALLBACK_FUNC_DECL(InspectorControllerSetting) if (key.isEmpty()) return v8::Undefined(); - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - const InspectorController::Setting& setting = inspectorController ->setting(key); + InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); + InspectorController* ic = inspectorBackend->inspectorController(); + if (!ic) + return v8::Undefined(); + const InspectorController::Setting& setting = ic->setting(key); switch (setting.type()) { default: @@ -186,9 +166,9 @@ CALLBACK_FUNC_DECL(InspectorControllerSetting) } } -CALLBACK_FUNC_DECL(InspectorControllerSetSetting) +CALLBACK_FUNC_DECL(InspectorBackendSetSetting) { - INC_STATS("InspectorController.setSetting()"); + INC_STATS("InspectorBackend.setSetting()"); if (args.Length() < 2) return v8::Undefined(); @@ -221,15 +201,17 @@ CALLBACK_FUNC_DECL(InspectorControllerSetSetting) } else return v8::Undefined(); - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - inspectorController->setSetting(key, setting); + InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); + InspectorController* ic = inspectorBackend->inspectorController(); + if (ic) + inspectorBackend->inspectorController()->setSetting(key, setting); return v8::Undefined(); } -CALLBACK_FUNC_DECL(InspectorControllerWrapCallback) +CALLBACK_FUNC_DECL(InspectorBackendWrapCallback) { - INC_STATS("InspectorController.wrapCallback()"); + INC_STATS("InspectorBackend.wrapCallback()"); return args[0]; } diff --git a/WebCore/bindings/v8/custom/V8LocationCustom.cpp b/WebCore/bindings/v8/custom/V8LocationCustom.cpp index c5f3b1d..3f3ff6b 100644 --- a/WebCore/bindings/v8/custom/V8LocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8LocationCustom.cpp @@ -62,7 +62,7 @@ ACCESSOR_SETTER(LocationHash) { INC_STATS("DOM.Location.hash._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String hash = toWebCoreString(value); Frame* frame = imp->frame(); @@ -70,13 +70,13 @@ ACCESSOR_SETTER(LocationHash) return; KURL url = frame->loader()->url(); - String oldRef = url.ref(); + String oldRef = url.fragmentIdentifier(); if (hash.startsWith("#")) hash = hash.substring(1); if (oldRef == hash || (oldRef.isNull() && hash.isEmpty())) return; - url.setRef(hash); + url.setFragmentIdentifier(hash); navigateIfAllowed(frame, url, false, false); } @@ -85,7 +85,7 @@ ACCESSOR_SETTER(LocationHost) { INC_STATS("DOM.Location.host._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String host = toWebCoreString(value); Frame* frame = imp->frame(); @@ -105,7 +105,7 @@ ACCESSOR_SETTER(LocationHostname) { INC_STATS("DOM.Location.hostname._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String hostname = toWebCoreString(value); Frame* frame = imp->frame(); @@ -122,7 +122,7 @@ ACCESSOR_SETTER(LocationHref) { INC_STATS("DOM.Location.href._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); Frame* frame = imp->frame(); if (!frame) @@ -142,7 +142,7 @@ ACCESSOR_SETTER(LocationPathname) { INC_STATS("DOM.Location.pathname._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String pathname = toWebCoreString(value); Frame* frame = imp->frame(); @@ -159,7 +159,7 @@ ACCESSOR_SETTER(LocationPort) { INC_STATS("DOM.Location.port._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String port = toWebCoreString(value); Frame* frame = imp->frame(); @@ -176,7 +176,7 @@ ACCESSOR_SETTER(LocationProtocol) { INC_STATS("DOM.Location.protocol._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String protocol = toWebCoreString(value); Frame* frame = imp->frame(); @@ -193,7 +193,7 @@ ACCESSOR_SETTER(LocationSearch) { INC_STATS("DOM.Location.search._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String query = toWebCoreString(value); Frame* frame = imp->frame(); @@ -210,14 +210,14 @@ ACCESSOR_GETTER(LocationReload) { INC_STATS("DOM.Location.reload._get"); static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), false)) { + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), false)) { static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); } else @@ -228,14 +228,14 @@ ACCESSOR_GETTER(LocationReplace) { INC_STATS("DOM.Location.replace._get"); static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReplaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), false)) { + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), false)) { static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReplaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); } else @@ -247,14 +247,14 @@ ACCESSOR_GETTER(LocationAssign) INC_STATS("DOM.Location.assign._get"); static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationAssignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), false)) { + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), false)) { static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationAssignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); } else @@ -266,8 +266,8 @@ CALLBACK_FUNC_DECL(LocationReload) // FIXME: we ignore the "forceget" parameter. INC_STATS("DOM.Location.reload"); - v8::Handle<v8::Value> holder = args.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + v8::Handle<v8::Object> holder = args.Holder(); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); Frame* frame = imp->frame(); if (!frame || !ScriptController::isSafeScript(frame)) @@ -281,8 +281,8 @@ CALLBACK_FUNC_DECL(LocationReload) CALLBACK_FUNC_DECL(LocationReplace) { INC_STATS("DOM.Location.replace"); - v8::Handle<v8::Value> holder = args.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + v8::Handle<v8::Object> holder = args.Holder(); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); Frame* frame = imp->frame(); if (!frame) @@ -302,8 +302,8 @@ CALLBACK_FUNC_DECL(LocationReplace) CALLBACK_FUNC_DECL(LocationAssign) { INC_STATS("DOM.Location.assign"); - v8::Handle<v8::Value> holder = args.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + v8::Handle<v8::Object> holder = args.Holder(); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); Frame* frame = imp->frame(); if (!frame) @@ -333,9 +333,9 @@ CALLBACK_FUNC_DECL(LocationValueOf) CALLBACK_FUNC_DECL(LocationToString) { INC_STATS("DOM.Location.toString"); - v8::Handle<v8::Value> holder = args.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + v8::Handle<v8::Object> holder = args.Holder(); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); String result = imp->href(); return v8String(result); @@ -345,16 +345,16 @@ INDEXED_ACCESS_CHECK(Location) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, host); - return V8Proxy::CanAccessFrame(imp->frame(), false); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); + return V8Proxy::canAccessFrame(imp->frame(), false); } NAMED_ACCESS_CHECK(Location) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, host); - return V8Proxy::CanAccessFrame(imp->frame(), false); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); + return V8Proxy::canAccessFrame(imp->frame(), false); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp index 3a41467..f45aecf 100644 --- a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp @@ -31,12 +31,14 @@ #include "config.h" #include "MessageChannel.h" -#include "Document.h" -#include "Frame.h" - #include "V8Binding.h" #include "V8Proxy.h" +#include "Document.h" +#include "Frame.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" + #include <wtf/RefPtr.h> namespace WebCore { @@ -44,32 +46,37 @@ namespace WebCore { CALLBACK_FUNC_DECL(MessageChannelConstructor) { INC_STATS("DOM.MessageChannel.Constructor"); - // FIXME: The logic here is almost exact duplicate of V8::ConstructDOMObject. + // FIXME: The logic here is almost exact duplicate of V8::constructDOMObject. // Consider refactoring to reduce duplication. if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - // Get the document. - Frame* frame = V8Proxy::retrieveFrame(); - if (!frame) - return v8::Undefined(); - - Document* document = frame->document(); + // Get the ScriptExecutionContext (WorkerContext or Document) + ScriptExecutionContext* context = 0; + WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + if (proxy) + context = proxy->workerContext(); + else { + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return v8::Undefined(); + context = frame->document(); + } // Note: it's OK to let this RefPtr go out of scope because we also call // SetDOMWrapper(), which effectively holds a reference to obj. - RefPtr<MessageChannel> obj = MessageChannel::create(document); + RefPtr<MessageChannel> obj = MessageChannel::create(context); v8::Local<v8::Object> messageChannel = args.Holder(); // Create references from the MessageChannel wrapper to the two // MessagePort wrappers to make sure that the MessagePort wrappers // stay alive as long as the MessageChannel wrapper is around. - messageChannel->SetInternalField(kMessageChannelPort1Index, V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, obj->port1())); - messageChannel->SetInternalField(kMessageChannelPort2Index, V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, obj->port2())); + messageChannel->SetInternalField(kMessageChannelPort1Index, V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, obj->port1())); + messageChannel->SetInternalField(kMessageChannelPort2Index, V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, obj->port2())); // Setup the standard wrapper object internal fields. - V8Proxy::SetDOMWrapper(messageChannel, V8ClassIndex::MESSAGECHANNEL, obj.get()); + V8DOMWrapper::setDOMWrapper(messageChannel, V8ClassIndex::MESSAGECHANNEL, obj.get()); return toV8(obj.release(), messageChannel); } diff --git a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp index fce04b6..95d248c 100644 --- a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp @@ -37,20 +37,38 @@ #include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" +#include "WorkerContextExecutionProxy.h" namespace WebCore { +PassRefPtr<EventListener> getEventListener(MessagePort* messagePort, v8::Local<v8::Value> value, bool findOnly, bool createObjectEventListener) +{ + V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, false) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); + } + +#if ENABLE(WORKERS) + WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); + if (workerContextProxy) + return workerContextProxy->findOrCreateEventListenerHelper(value, false, findOnly, createObjectEventListener); +#endif + + return PassRefPtr<EventListener>(); +} + ACCESSOR_GETTER(MessagePortOnmessage) { INC_STATS("DOM.MessagePort.onmessage._get"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); - return V8Proxy::EventListenerToV8Object(messagePort->onmessage()); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); + return V8DOMWrapper::convertEventListenerToV8Object(messagePort->onmessage()); } ACCESSOR_SETTER(MessagePortOnmessage) { INC_STATS("DOM.MessagePort.onmessage._set"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); if (value->IsNull()) { if (messagePort->onmessage()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(messagePort->onmessage()); @@ -61,11 +79,7 @@ ACCESSOR_SETTER(MessagePortOnmessage) messagePort->setOnmessage(0); } else { - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = getEventListener(messagePort, value, false, false); if (listener) { messagePort->setOnmessage(listener); createHiddenDependency(info.Holder(), value, V8Custom::kMessagePortRequestCacheIndex); @@ -73,64 +87,11 @@ ACCESSOR_SETTER(MessagePortOnmessage) } } -ACCESSOR_GETTER(MessagePortOnclose) -{ - INC_STATS("DOM.MessagePort.onclose._get"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); - return V8Proxy::EventListenerToV8Object(messagePort->onclose()); -} - -ACCESSOR_SETTER(MessagePortOnclose) -{ - INC_STATS("DOM.MessagePort.onclose._set"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); - if (value->IsNull()) { - if (messagePort->onclose()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(messagePort->onclose()); - removeHiddenDependency(info.Holder(), listener->getListenerObject(), V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - messagePort->setOnclose(0); - } else { - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); - if (listener) { - messagePort->setOnclose(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kMessagePortRequestCacheIndex); - } - } -} - -CALLBACK_FUNC_DECL(MessagePortStartConversation) -{ - INC_STATS("DOM.MessagePort.StartConversation()"); - if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<MessagePort> port = messagePort->startConversation(messagePort->scriptExecutionContext(), toWebCoreString(args[0])); - v8::Handle<v8::Value> wrapper = V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, port.get()); - return wrapper; -} - CALLBACK_FUNC_DECL(MessagePortAddEventListener) { - INC_STATS("DOM.MessagePort.AddEventListener()"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(args[1], false); + INC_STATS("DOM.MessagePort.addEventListener()"); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); + RefPtr<EventListener> listener = getEventListener(messagePort, args[1], false, true); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -143,15 +104,9 @@ CALLBACK_FUNC_DECL(MessagePortAddEventListener) CALLBACK_FUNC_DECL(MessagePortRemoveEventListener) { - INC_STATS("DOM.MessagePort.RemoveEventListener()"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); // probably leaked - - RefPtr<EventListener> listener = proxy->FindObjectEventListener(args[1], false); - + INC_STATS("DOM.MessagePort.removeEventListener()"); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); + RefPtr<EventListener> listener = getEventListener(messagePort, args[1], true, true); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); diff --git a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp index 8e529cc..afa90b7 100644 --- a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp @@ -42,12 +42,12 @@ namespace WebCore { INDEXED_PROPERTY_GETTER(NamedNodeMap) { INC_STATS("DOM.NamedNodeMap.IndexedPropertyGetter"); - NamedNodeMap* imp = V8Proxy::ToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); + NamedNodeMap* imp = V8DOMWrapper::convertToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); RefPtr<Node> result = imp->item(index); if (!result) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } NAMED_PROPERTY_GETTER(NamedNodeMap) @@ -63,12 +63,12 @@ NAMED_PROPERTY_GETTER(NamedNodeMap) return notHandledByInterceptor(); // Finally, search the DOM. - NamedNodeMap* imp = V8Proxy::ToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); + NamedNodeMap* imp = V8DOMWrapper::convertToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); RefPtr<Node> result = imp->getNamedItem(toWebCoreString(name)); if (!result) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp b/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp index 9adfe25..6a7b209 100644 --- a/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp @@ -41,7 +41,7 @@ ACCESSOR_GETTER(NavigatorAppVersion) { INC_STATS("DOM.Navigator.appVersion"); v8::Handle<v8::Object> holder = info.Holder(); - Navigator* navigator = V8Proxy::ToNativeObject<Navigator>(V8ClassIndex::NAVIGATOR, holder); + Navigator* navigator = V8DOMWrapper::convertToNativeObject<Navigator>(V8ClassIndex::NAVIGATOR, holder); return v8StringOrUndefined(navigator->appVersion()); } diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp index e81e8b5..6b0d740 100644 --- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp @@ -34,30 +34,86 @@ #include "Document.h" #include "EventListener.h" +#include "V8AbstractEventListener.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8CustomEventListener.h" #include "V8Node.h" +#include "V8ObjectEventListener.h" #include "V8Proxy.h" #include <wtf/RefPtr.h> namespace WebCore { -CALLBACK_FUNC_DECL(NodeAddEventListener) +static inline String toEventType(v8::Local<v8::String> value) { - INC_STATS("DOM.Node.addEventListener()"); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args.Holder()); + String key = toWebCoreString(value); + ASSERT(key.startsWith("on")); + return key.substring(2); +} - V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); +static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) +{ + V8Proxy* proxy = V8Proxy::retrieve(node->scriptExecutionContext()); + // The document might be created using createDocument, which does + // not have a frame, use the active frame. if (!proxy) - return v8::Undefined(); + proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext()); + + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); + } + + return 0; +} + +ACCESSOR_SETTER(NodeEventHandler) +{ + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder()); + String eventType = toEventType(name); + + // Remove hidden dependency on the old event handler. + if (EventListener* listener = node->getAttributeEventListener(eventType)) { + if (static_cast<V8AbstractEventListener*>(listener)->isObjectListener()) { + v8::Local<v8::Object> v8Listener = static_cast<V8ObjectEventListener*>(listener)->getListenerObject(); + removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kNodeEventListenerCacheIndex); + } + } + + // Set handler if the value is a function. + if (value->IsFunction()) { + RefPtr<EventListener> listener = getEventListener(node, value, true, false); + if (listener) { + node->setAttributeEventListener(eventType, listener); + createHiddenDependency(info.Holder(), value, V8Custom::kNodeEventListenerCacheIndex); + } + } else { + // Otherwise, clear the handler. + node->clearAttributeEventListener(eventType); + } +} + +ACCESSOR_GETTER(NodeEventHandler) +{ + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder()); + + EventListener* listener = node->getAttributeEventListener(toEventType(name)); + return V8DOMWrapper::convertEventListenerToV8Object(listener); +} - RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(args[1], false); +CALLBACK_FUNC_DECL(NodeAddEventListener) +{ + INC_STATS("DOM.Node.addEventListener()"); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); + + RefPtr<EventListener> listener = getEventListener(node, args[1], false, false); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); node->addEventListener(type, listener, useCapture); + createHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); } return v8::Undefined(); } @@ -65,20 +121,17 @@ CALLBACK_FUNC_DECL(NodeAddEventListener) CALLBACK_FUNC_DECL(NodeRemoveEventListener) { INC_STATS("DOM.Node.removeEventListener()"); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args.Holder()); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); - V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); // It is possbile that the owner document of the node is detached - // from the frame, return immediately in this case. + // from the frame. // See issue http://b/878909 - if (!proxy) - return v8::Undefined(); - - RefPtr<EventListener> listener = proxy->FindV8EventListener(args[1], false); + RefPtr<EventListener> listener = getEventListener(node, args[1], false, true); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); node->removeEventListener(type, listener.get(), useCapture); + removeHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); } return v8::Undefined(); @@ -88,14 +141,14 @@ CALLBACK_FUNC_DECL(NodeRemoveEventListener) CALLBACK_FUNC_DECL(NodeInsertBefore) { INC_STATS("DOM.Node.insertBefore"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; - Node* refChild = V8Node::HasInstance(args[1]) ? V8Proxy::DOMWrapperToNode<Node>(args[1]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; + Node* refChild = V8Node::HasInstance(args[1]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])) : 0; bool success = imp->insertBefore(newChild, refChild, ec, true); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -107,14 +160,14 @@ CALLBACK_FUNC_DECL(NodeInsertBefore) CALLBACK_FUNC_DECL(NodeReplaceChild) { INC_STATS("DOM.Node.replaceChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; - Node* oldChild = V8Node::HasInstance(args[1]) ? V8Proxy::DOMWrapperToNode<Node>(args[1]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; + Node* oldChild = V8Node::HasInstance(args[1]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])) : 0; bool success = imp->replaceChild(newChild, oldChild, ec, true); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -125,13 +178,13 @@ CALLBACK_FUNC_DECL(NodeReplaceChild) CALLBACK_FUNC_DECL(NodeRemoveChild) { INC_STATS("DOM.Node.removeChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* oldChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; + Node* oldChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->removeChild(oldChild, ec); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -143,13 +196,13 @@ CALLBACK_FUNC_DECL(NodeRemoveChild) CALLBACK_FUNC_DECL(NodeAppendChild) { INC_STATS("DOM.Node.appendChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->appendChild(newChild, ec, true ); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) diff --git a/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp b/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp index 48e6b8f..47ae8ee 100644 --- a/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp @@ -53,13 +53,13 @@ static inline v8::Handle<v8::Value> toV8(PassRefPtr<Node> object, ExceptionCode if (!object) return v8::Null(); - return V8Proxy::NodeToV8Object(object.get()); + return V8DOMWrapper::convertNodeToV8Object(object); } CALLBACK_FUNC_DECL(NodeIteratorNextNode) { INC_STATS("DOM.NodeIterator.nextNode()"); - NodeIterator* nodeIterator = V8Proxy::ToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); + NodeIterator* nodeIterator = V8DOMWrapper::convertToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); ExceptionCode ec = 0; ScriptState state; @@ -70,7 +70,7 @@ CALLBACK_FUNC_DECL(NodeIteratorNextNode) CALLBACK_FUNC_DECL(NodeIteratorPreviousNode) { INC_STATS("DOM.NodeIterator.previousNode()"); - NodeIterator* nodeIterator = V8Proxy::ToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); + NodeIterator* nodeIterator = V8DOMWrapper::convertToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); ExceptionCode ec = 0; ScriptState state; diff --git a/WebCore/bindings/v8/custom/V8NodeListCustom.cpp b/WebCore/bindings/v8/custom/V8NodeListCustom.cpp index 27a47f5..ad10952 100644 --- a/WebCore/bindings/v8/custom/V8NodeListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeListCustom.cpp @@ -36,24 +36,26 @@ #include "V8Proxy.h" #include <wtf/RefPtr.h> +#include <wtf/StdLibExtras.h> namespace WebCore { NAMED_PROPERTY_GETTER(NodeList) { INC_STATS("DOM.NodeList.NamedPropertyGetter"); - NodeList* list = V8Proxy::ToNativeObject<NodeList>(V8ClassIndex::NODELIST, info.Holder()); + NodeList* list = V8DOMWrapper::convertToNativeObject<NodeList>(V8ClassIndex::NODELIST, info.Holder()); String key = toWebCoreString(name); // Length property cannot be overridden. - if (key == "length") - return v8::Number::New(list->length()); + DEFINE_STATIC_LOCAL(const AtomicString, length, ("length")); + if (key == length) + return v8::Integer::New(list->length()); RefPtr<Node> result = list->itemWithName(key); if (!result) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp b/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp index eaeb26d..aced4ee 100644 --- a/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp @@ -32,11 +32,20 @@ #if ENABLE(DATABASE) +#ifdef MANUAL_MERGE_REQUIRED #include "v8_binding.h" #include "v8_proxy.h" +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED #include "SQLResultSetRowList.h" +#ifdef MANUAL_MERGE_REQUIRED #include "V8CustomBinding.h" +#else // MANUAL_MERGE_REQUIRED +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" +#endif // MANUAL_MERGE_REQUIRED namespace WebCore { @@ -45,20 +54,20 @@ CALLBACK_FUNC_DECL(SQLResultSetRowListItem) INC_STATS("DOM.SQLResultSetRowList.item()"); if (args.Length() == 0) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Item index is required."); + V8Proxy::throwError(V8Proxy::SyntaxError, "Item index is required."); return v8::Undefined(); } if (!args[0]->IsNumber()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Item index must be a number."); + V8Proxy::throwError(V8Proxy::TypeError, "Item index must be a number."); return v8::Undefined(); } - SQLResultSetRowList* rowList = V8Proxy::ToNativeObject<SQLResultSetRowList>(V8ClassIndex::SQLRESULTSETROWLIST, args.Holder()); + SQLResultSetRowList* rowList = V8DOMWrapper::convertToNativeObject<SQLResultSetRowList>(V8ClassIndex::SQLRESULTSETROWLIST, args.Holder()); unsigned long index = args[0]->IntegerValue(); if (index < 0 || index >= rowList->length()) { - V8Proxy::ThrowError(V8Proxy::RANGE_ERROR, "Item index is out of range."); + V8Proxy::throwError(V8Proxy::RangeError, "Item index is out of range."); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp index 15cd379..b9b86fc 100644 --- a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp @@ -32,14 +32,23 @@ #if ENABLE(DATABASE) +#ifdef MANUAL_MERGE_REQUIRED #include "v8_binding.h" #include "v8_proxy.h" +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED #include "Database.h" #include "SQLValue.h" +#ifdef MANUAL_MERGE_REQUIRED #include "V8CustomBinding.h" +#else // MANUAL_MERGE_REQUIRED +#include "V8Binding.h" +#include "V8CustomBinding.h" +#endif // MANUAL_MERGE_REQUIRED #include "V8CustomSQLStatementCallback.h" #include "V8CustomSQLStatementErrorCallback.h" +#include "V8Proxy.h" #include <wtf/Vector.h> using namespace WTF; @@ -51,18 +60,18 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) INC_STATS("DOM.SQLTransaction.executeSql()"); if (args.Length() == 0) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "SQL statement is required."); + V8Proxy::throwError(V8Proxy::SyntaxError, "SQL statement is required."); return v8::Undefined(); } - String statement = ToWebCoreString(args[0]); + String statement = toWebCoreString(args[0]); Vector<SQLValue> sqlValues; if (args.Length() > 1) { // FIXME: Make this work for v8::Arrayish objects, as well if (!args[1]->IsArray()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Statement arguments must be an v8::Array."); + V8Proxy::throwError(V8Proxy::TypeError, "Statement arguments must be an v8::Array."); return v8::Undefined(); } @@ -76,18 +85,18 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) else if (value->IsNumber()) sqlValues.append(SQLValue(value->NumberValue())); else - sqlValues.append(SQLValue(ToWebCoreString(value))); + sqlValues.append(SQLValue(toWebCoreString(value))); } } - SQLTransaction* transaction = V8Proxy::ToNativeObject<SQLTransaction>(V8ClassIndex::SQLTRANSACTION, args.Holder()); + SQLTransaction* transaction = V8DOMWrapper::convertToNativeObject<SQLTransaction>(V8ClassIndex::SQLTRANSACTION, args.Holder()); - Frame* frame = V8Proxy::retrieveFrame(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); RefPtr<SQLStatementCallback> callback; if (args.Length() > 2) { if (!args[2]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Statement callback must be of valid type."); + V8Proxy::throwError(V8Proxy::TypeError, "Statement callback must be of valid type."); return v8::Undefined(); } @@ -98,7 +107,7 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) RefPtr<SQLStatementErrorCallback> errorCallback; if (args.Length() > 3) { if (!args[2]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Statement error callback must be of valid type."); + V8Proxy::throwError(V8Proxy::TypeError, "Statement error callback must be of valid type."); return v8::Undefined(); } @@ -108,7 +117,7 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) ExceptionCode ec = 0; transaction->executeSQL(statement, sqlValues, callback, errorCallback, ec); - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp index 351b030..ce9c345 100644 --- a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp @@ -47,13 +47,13 @@ namespace WebCore { CALLBACK_FUNC_DECL(SVGElementInstanceAddEventListener) { INC_STATS("DOM.SVGElementInstance.AddEventListener()"); - SVGElementInstance* instance = V8Proxy::DOMWrapperToNative<SVGElementInstance>(args.Holder()); + SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder()); V8Proxy* proxy = V8Proxy::retrieve(instance->scriptExecutionContext()); if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(args[1], false); + RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -66,13 +66,13 @@ CALLBACK_FUNC_DECL(SVGElementInstanceAddEventListener) CALLBACK_FUNC_DECL(SVGElementInstanceRemoveEventListener) { INC_STATS("DOM.SVGElementInstance.RemoveEventListener()"); - SVGElementInstance* instance = V8Proxy::DOMWrapperToNative<SVGElementInstance>(args.Holder()); + SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder()); V8Proxy* proxy = V8Proxy::retrieve(instance->scriptExecutionContext()); if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindV8EventListener(args[1], false); + RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); diff --git a/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp b/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp index a2a4d49..9f75f5a 100644 --- a/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp @@ -44,17 +44,17 @@ namespace WebCore { ACCESSOR_GETTER(SVGLengthValue) { INC_STATS("DOM.SVGLength.value"); - V8SVGPODTypeWrapper<SVGLength>* wrapper = V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, info.Holder()); + V8SVGPODTypeWrapper<SVGLength>* wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, info.Holder()); SVGLength imp = *wrapper; - return v8::Number::New(imp.value(V8Proxy::GetSVGContext(wrapper))); + return v8::Number::New(imp.value(V8Proxy::svgContext(wrapper))); } CALLBACK_FUNC_DECL(SVGLengthConvertToSpecifiedUnits) { INC_STATS("DOM.SVGLength.convertToSpecifiedUnits"); - V8SVGPODTypeWrapper<SVGLength>* wrapper = V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, args.Holder()); + V8SVGPODTypeWrapper<SVGLength>* wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, args.Holder()); SVGLength imp = *wrapper; - SVGElement* context = V8Proxy::GetSVGContext(wrapper); + SVGElement* context = V8Proxy::svgContext(wrapper); imp.convertToSpecifiedUnits(toInt32(args[0]), context); wrapper->commitChange(imp, context); return v8::Undefined(); diff --git a/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp b/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp index b69202b..3766397 100644 --- a/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp @@ -46,7 +46,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(SVGMatrixInverse) { INC_STATS("DOM.SVGMatrix.inverse()"); - TransformationMatrix matrix = *V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); + TransformationMatrix matrix = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); ExceptionCode ec = 0; TransformationMatrix result = matrix.inverse(); @@ -54,17 +54,17 @@ CALLBACK_FUNC_DECL(SVGMatrixInverse) ec = SVGException::SVG_MATRIX_NOT_INVERTABLE; if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } - return V8Proxy::ToV8Object(V8ClassIndex::SVGMATRIX, new V8SVGStaticPODTypeWrapper<TransformationMatrix>(result)); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGMATRIX, V8SVGStaticPODTypeWrapper<TransformationMatrix>::create(result)); } CALLBACK_FUNC_DECL(SVGMatrixRotateFromVector) { INC_STATS("DOM.SVGMatrix.rotateFromVector()"); - TransformationMatrix matrix = *V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); + TransformationMatrix matrix = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); ExceptionCode ec = 0; float x = toFloat(args[0]); float y = toFloat(args[1]); @@ -74,11 +74,11 @@ CALLBACK_FUNC_DECL(SVGMatrixRotateFromVector) ec = SVGException::SVG_INVALID_VALUE_ERR; if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } - return V8Proxy::ToV8Object(V8ClassIndex::SVGMATRIX, new V8SVGStaticPODTypeWrapper<TransformationMatrix>(result)); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGMATRIX, V8SVGStaticPODTypeWrapper<TransformationMatrix>::create(result)); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp new file mode 100644 index 0000000..3ab2f8e --- /dev/null +++ b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(SHARED_WORKERS) + +#include "SharedWorker.h" + +#include "ExceptionCode.h" +#include "Frame.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8ObjectEventListener.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(SharedWorkerConstructor) +{ + INC_STATS(L"DOM.SharedWorker.Constructor"); + + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function."); + + if (args.Length() < 2) + return throwError("Not enough arguments", V8Proxy::SyntaxError); + + v8::TryCatch tryCatch; + v8::Handle<v8::String> scriptUrl = args[0]->ToString(); + v8::Handle<v8::String> name = args[1]->ToString(); + if (tryCatch.HasCaught()) + return throwError(tryCatch.Exception()); + + if (scriptUrl.IsEmpty()) + return v8::Undefined(); + + // Get the script execution context. + ScriptExecutionContext* context = 0; + WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + if (proxy) + context = proxy->workerContext(); + else { + Frame* frame = V8Proxy::retrieveFrame(); + if (!frame) + return v8::Undefined(); + context = frame->document(); + } + + // Create the worker object. + // Note: it's OK to let this RefPtr go out of scope because we also call SetDOMWrapper(), which effectively holds a reference to obj. + ExceptionCode ec = 0; + RefPtr<SharedWorker> obj = SharedWorker::create(toWebCoreString(scriptUrl), toWebCoreString(name), context, ec); + + // Setup the standard wrapper object internal fields. + v8::Handle<v8::Object> wrapperObject = args.Holder(); + V8Proxy::setDOMWrapper(wrapperObject, V8ClassIndex::SHAREDWORKER, obj.get()); + + obj->ref(); + V8Proxy::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); + + return wrapperObject; +} + +} // namespace WebCore + +#endif // ENABLE(SHARED_WORKERS) diff --git a/WebCore/bindings/v8/custom/V8StorageCustom.cpp b/WebCore/bindings/v8/custom/V8StorageCustom.cpp index af8b4c8..b54e50e 100755 --- a/WebCore/bindings/v8/custom/V8StorageCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StorageCustom.cpp @@ -42,13 +42,12 @@ namespace WebCore { // Get an array containing the names of indexed properties in a collection. v8::Handle<v8::Array> V8Custom::v8StorageNamedPropertyEnumerator(const v8::AccessorInfo& info) { - Storage* storage = V8Proxy::ToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); unsigned int length = storage->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (unsigned int i = 0; i < length; ++i) { - ExceptionCode ec = 0; - String key = storage->key(i, ec); - ASSERT(!ec); + String key = storage->key(i); + ASSERT(!key.isNull()); String val = storage->getItem(key); properties->Set(v8::Integer::New(i), v8String(key)); } @@ -58,7 +57,7 @@ v8::Handle<v8::Array> V8Custom::v8StorageNamedPropertyEnumerator(const v8::Acces static v8::Handle<v8::Value> storageGetter(v8::Local<v8::String> v8Name, const v8::AccessorInfo& info) { - Storage* storage = V8Proxy::ToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); String name = toWebCoreString(v8Name); if (storage->contains(name)) @@ -82,7 +81,7 @@ NAMED_PROPERTY_GETTER(Storage) static v8::Handle<v8::Value> storageSetter(v8::Local<v8::String> v8Name, v8::Local<v8::Value> v8Value, const v8::AccessorInfo& info) { - Storage* storage = V8Proxy::ToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); String name = toWebCoreString(v8Name); String value = toWebCoreString(v8Value); @@ -117,7 +116,7 @@ NAMED_PROPERTY_SETTER(Storage) static v8::Handle<v8::Boolean> storageDeleter(v8::Local<v8::String> v8Name, const v8::AccessorInfo& info) { - Storage* storage = V8Proxy::ToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); String name = toWebCoreString(v8Name); if (storage->contains(name)) { diff --git a/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp b/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp index a362ce5..ecd0153 100644 --- a/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp @@ -45,12 +45,12 @@ NAMED_PROPERTY_GETTER(StyleSheetList) return notHandledByInterceptor(); // Search style sheet. - StyleSheetList* imp = V8Proxy::ToNativeObject<StyleSheetList>(V8ClassIndex::STYLESHEETLIST, info.Holder()); + StyleSheetList* imp = V8DOMWrapper::convertToNativeObject<StyleSheetList>(V8ClassIndex::STYLESHEETLIST, info.Holder()); HTMLStyleElement* item = imp->getNamedItem(toWebCoreString(name)); if (!item) return notHandledByInterceptor(); - return V8Proxy::ToV8Object(V8ClassIndex::HTMLSTYLEELEMENT, item); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLSTYLEELEMENT, item); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp b/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp index baf49c0..5052b7a 100644 --- a/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp @@ -51,13 +51,13 @@ static inline v8::Handle<v8::Value> toV8(PassRefPtr<Node> object, ScriptState* s if (!object) return v8::Null(); - return V8Proxy::NodeToV8Object(object.get()); + return V8DOMWrapper::convertNodeToV8Object(object); } CALLBACK_FUNC_DECL(TreeWalkerParentNode) { INC_STATS("DOM.TreeWalker.parentNode()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->parentNode(&state); @@ -67,7 +67,7 @@ CALLBACK_FUNC_DECL(TreeWalkerParentNode) CALLBACK_FUNC_DECL(TreeWalkerFirstChild) { INC_STATS("DOM.TreeWalker.firstChild()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->firstChild(&state); @@ -77,7 +77,7 @@ CALLBACK_FUNC_DECL(TreeWalkerFirstChild) CALLBACK_FUNC_DECL(TreeWalkerLastChild) { INC_STATS("DOM.TreeWalker.lastChild()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->lastChild(&state); @@ -87,7 +87,7 @@ CALLBACK_FUNC_DECL(TreeWalkerLastChild) CALLBACK_FUNC_DECL(TreeWalkerNextNode) { INC_STATS("DOM.TreeWalker.nextNode()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->nextNode(&state); @@ -97,7 +97,7 @@ CALLBACK_FUNC_DECL(TreeWalkerNextNode) CALLBACK_FUNC_DECL(TreeWalkerPreviousNode) { INC_STATS("DOM.TreeWalker.previousNode()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->previousNode(&state); @@ -107,7 +107,7 @@ CALLBACK_FUNC_DECL(TreeWalkerPreviousNode) CALLBACK_FUNC_DECL(TreeWalkerNextSibling) { INC_STATS("DOM.TreeWalker.nextSibling()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->nextSibling(&state); @@ -117,7 +117,7 @@ CALLBACK_FUNC_DECL(TreeWalkerNextSibling) CALLBACK_FUNC_DECL(TreeWalkerPreviousSibling) { INC_STATS("DOM.TreeWalker.previousSibling()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->previousSibling(&state); diff --git a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp index b07d288..4819064 100644 --- a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp @@ -47,7 +47,11 @@ namespace WebCore { CALLBACK_FUNC_DECL(WebKitCSSMatrixConstructor) { INC_STATS("DOM.WebKitCSSMatrix.Constructor"); - // FIXME: The logic here is almost exact duplicate of V8::ConstructDOMObject. + + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function."); + + // FIXME: The logic here is almost exact duplicate of V8::constructDOMObject. // Consider refactoring to reduce duplication. String cssValue; if (args.Length() >= 1) @@ -59,7 +63,7 @@ CALLBACK_FUNC_DECL(WebKitCSSMatrixConstructor) throwError(ec); // Transform the holder into a wrapper object for the matrix. - V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBKITCSSMATRIX), matrix.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBKITCSSMATRIX), matrix.get()); return toV8(matrix.release(), args.Holder()); } diff --git a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp index d70ebf1..dd19a88 100755 --- a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp @@ -40,7 +40,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(WebKitPointConstructor) { INC_STATS("DOM.WebKitPoint.Constructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::WEBKITPOINT, WebKitPoint>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::WEBKITPOINT, WebKitPoint>(args); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp index a67cb10..b526040 100755 --- a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp @@ -32,11 +32,8 @@ #if ENABLE(WORKERS) -#include "WorkerContextExecutionProxy.h" - -#include "ExceptionCode.h" #include "DOMTimer.h" -#include "NotImplemented.h" +#include "ExceptionCode.h" #include "ScheduledAction.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -44,50 +41,51 @@ #include "V8Utilities.h" #include "V8WorkerContextEventListener.h" #include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" namespace WebCore { ACCESSOR_GETTER(WorkerContextSelf) { INC_STATS(L"DOM.WorkerContext.self._get"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - return WorkerContextExecutionProxy::WorkerContextToV8Object(workerContext); + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(info.Holder()); + return WorkerContextExecutionProxy::convertWorkerContextToV8Object(workerContext); } -ACCESSOR_GETTER(WorkerContextOnmessage) +ACCESSOR_GETTER(WorkerContextOnerror) { - INC_STATS(L"DOM.WorkerContext.onmessage._get"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - if (workerContext->onmessage()) { - V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); + INC_STATS(L"DOM.WorkerContext.onerror._get"); + WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); + if (workerContext->onerror()) { + V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onerror()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); return v8Listener; } return v8::Undefined(); } -ACCESSOR_SETTER(WorkerContextOnmessage) +ACCESSOR_SETTER(WorkerContextOnerror) { - INC_STATS(L"DOM.WorkerContext.onmessage._set"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); + INC_STATS(L"DOM.WorkerContext.onerror._set"); + WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); + V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onerror()); if (value->IsNull()) { - if (workerContext->onmessage()) { + if (workerContext->onerror()) { v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex); } // Clear the listener. - workerContext->setOnmessage(0); + workerContext->setOnerror(0); } else { - RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), false, false); + RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), true, false); if (listener) { if (oldListener) { v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex); } - workerContext->setOnmessage(listener); + workerContext->setOnerror(listener); createHiddenDependency(info.Holder(), value, V8Custom::kWorkerContextRequestCacheIndex); } } @@ -95,7 +93,7 @@ ACCESSOR_SETTER(WorkerContextOnmessage) v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singleShot) { - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder()); + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); int argumentCount = args.Length(); if (argumentCount < 1) @@ -106,7 +104,7 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl int timerId; if (function->IsString()) { - WebCore::String stringFunction = ToWebCoreString(function); + WebCore::String stringFunction = toWebCoreString(function); timerId = DOMTimer::install(workerContext, new ScheduledAction(stringFunction, workerContext->url()), timeout, singleShot); } else if (function->IsFunction()) { size_t paramCount = argumentCount >= 2 ? argumentCount - 2 : 0; @@ -129,7 +127,29 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl CALLBACK_FUNC_DECL(WorkerContextImportScripts) { INC_STATS(L"DOM.WorkerContext.importScripts()"); - notImplemented(); + if (!args.Length()) + return v8::Undefined(); + + String callerURL = V8Proxy::sourceName(); + int callerLine = V8Proxy::sourceLineNumber() + 1; + + Vector<String> urls; + for (int i = 0; i < args.Length(); i++) { + v8::TryCatch tryCatch; + v8::Handle<v8::String> scriptUrl = args[i]->ToString(); + if (tryCatch.HasCaught() || scriptUrl.IsEmpty()) + return v8::Undefined(); + urls.append(toWebCoreString(scriptUrl)); + } + + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); + + ExceptionCode ec = 0; + workerContext->importScripts(urls, callerURL, callerLine, ec); + + if (ec) + return throwError(ec); + return v8::Undefined(); } @@ -139,7 +159,8 @@ CALLBACK_FUNC_DECL(WorkerContextSetTimeout) return SetTimeoutOrInterval(args, true); } -CALLBACK_FUNC_DECL(WorkerContextSetInterval) { +CALLBACK_FUNC_DECL(WorkerContextSetInterval) +{ INC_STATS(L"DOM.WorkerContext.setInterval()"); return SetTimeoutOrInterval(args, false); } @@ -147,7 +168,7 @@ CALLBACK_FUNC_DECL(WorkerContextSetInterval) { CALLBACK_FUNC_DECL(WorkerContextAddEventListener) { INC_STATS(L"DOM.WorkerContext.addEventListener()"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder()); + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, false); @@ -164,7 +185,7 @@ CALLBACK_FUNC_DECL(WorkerContextAddEventListener) CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener) { INC_STATS(L"DOM.WorkerContext.removeEventListener()"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder()); + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); WorkerContextExecutionProxy* proxy = workerContext->script()->proxy(); RefPtr<V8EventListener> listener = proxy->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, true); diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp index 3edaa8e..32450b8 100755 --- a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp @@ -50,23 +50,17 @@ CALLBACK_FUNC_DECL(WorkerConstructor) { INC_STATS(L"DOM.Worker.Constructor"); - if (!WorkerContextExecutionProxy::isWebWorkersEnabled()) { - return throwError("Worker is not enabled.", V8Proxy::SYNTAX_ERROR); - } - - if (!args.IsConstructCall()) { + if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - } - if (args.Length() == 0) { - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); - } + if (!args.Length()) + return throwError("Not enough arguments", V8Proxy::SyntaxError); v8::TryCatch tryCatch; v8::Handle<v8::String> scriptUrl = args[0]->ToString(); - if (tryCatch.HasCaught()) { + if (tryCatch.HasCaught()) return throwError(tryCatch.Exception()); - } + if (scriptUrl.IsEmpty()) return v8::Undefined(); @@ -76,38 +70,42 @@ CALLBACK_FUNC_DECL(WorkerConstructor) if (proxy) context = proxy->workerContext(); else { - Frame* frame = V8Proxy::retrieveFrame(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); if (!frame) return v8::Undefined(); context = frame->document(); } // Create the worker object. - // Note: it's OK to let this RefPtr go out of scope because we also call SetDOMWrapper(), which effectively holds a reference to obj. + // Note: it's OK to let this RefPtr go out of scope because we also call setDOMWrapper(), which effectively holds a reference to obj. ExceptionCode ec = 0; RefPtr<Worker> obj = Worker::create(toWebCoreString(scriptUrl), context, ec); + if (ec) + return throwError(ec); // Setup the standard wrapper object internal fields. v8::Handle<v8::Object> wrapperObject = args.Holder(); - V8Proxy::SetDOMWrapper(wrapperObject, V8ClassIndex::WORKER, obj.get()); + V8DOMWrapper::setDOMWrapper(wrapperObject, V8ClassIndex::WORKER, obj.get()); obj->ref(); - V8Proxy::SetJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); + V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); return wrapperObject; } -PassRefPtr<EventListener> getEventListener(Worker* worker, v8::Local<v8::Value> value, bool findOnly) +PassRefPtr<EventListener> getEventListener(Worker* worker, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) { if (worker->scriptExecutionContext()->isWorkerContext()) { WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); ASSERT(workerContextProxy); - return workerContextProxy->findOrCreateObjectEventListener(value, false, findOnly); + return workerContextProxy->findOrCreateObjectEventListener(value, isAttribute, findOnly); } V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext()); - if (proxy) - return findOnly ? proxy->FindObjectEventListener(value, false) : proxy->FindOrCreateObjectEventListener(value, false); + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); + } return 0; } @@ -115,7 +113,7 @@ PassRefPtr<EventListener> getEventListener(Worker* worker, v8::Local<v8::Value> ACCESSOR_GETTER(WorkerOnmessage) { INC_STATS(L"DOM.Worker.onmessage._get"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); + Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); if (worker->onmessage()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onmessage()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -127,7 +125,7 @@ ACCESSOR_GETTER(WorkerOnmessage) ACCESSOR_SETTER(WorkerOnmessage) { INC_STATS(L"DOM.Worker.onmessage._set"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); + Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onmessage()); if (value->IsNull()) { if (oldListener) { @@ -138,7 +136,7 @@ ACCESSOR_SETTER(WorkerOnmessage) // Clear the listener. worker->setOnmessage(0); } else { - RefPtr<EventListener> listener = getEventListener(worker, value, false); + RefPtr<EventListener> listener = getEventListener(worker, value, true, false); if (listener) { if (oldListener) { v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); @@ -151,78 +149,6 @@ ACCESSOR_SETTER(WorkerOnmessage) } } -ACCESSOR_GETTER(WorkerOnerror) -{ - INC_STATS(L"DOM.Worker.onerror._get"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); - if (worker->onerror()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onerror()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(WorkerOnerror) -{ - INC_STATS(L"DOM.Worker.onerror._set"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); - V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onerror()); - if (value->IsNull()) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex); - } - - // Clear the listener. - worker->setOnerror(0); - } else { - RefPtr<EventListener> listener = getEventListener(worker, value, false); - if (listener) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex); - } - - worker->setOnerror(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kWorkerRequestCacheIndex); - } - } -} - -CALLBACK_FUNC_DECL(WorkerAddEventListener) -{ - INC_STATS(L"DOM.Worker.addEventListener()"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder()); - - RefPtr<EventListener> listener = getEventListener(worker, args[1], false); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - worker->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerRequestCacheIndex); - } - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(WorkerRemoveEventListener) -{ - INC_STATS(L"DOM.Worker.removeEventListener()"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder()); - - RefPtr<EventListener> listener = getEventListener(worker, args[1], true); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - worker->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerRequestCacheIndex); - } - - return v8::Undefined(); -} - } // namespace WebCore #endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp index c913c08..02ce8e2 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp @@ -46,7 +46,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) INC_STATS("DOM.XMLHttpRequest.Constructor"); if (!args.IsConstructCall()) - return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TYPE_ERROR); + return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError); // Expect no parameters. // Allocate a XMLHttpRequest object as its internal field. @@ -55,15 +55,21 @@ CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); if (proxy) context = proxy->workerContext(); - else + else { +#endif + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("XMLHttpRequest constructor's associated frame is not available", V8Proxy::ReferenceError); + context = frame->document(); +#if ENABLE(WORKERS) + } #endif - context = V8Proxy::retrieveFrame()->document(); RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context); - V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xmlHttpRequest.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xmlHttpRequest.get()); // Add object to the wrapper map. xmlHttpRequest->ref(); - V8Proxy::SetJSWrapperForActiveDOMObject(xmlHttpRequest.get(), v8::Persistent<v8::Object>::New(args.Holder())); + V8DOMWrapper::setJSWrapperForActiveDOMObject(xmlHttpRequest.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp index cb80a4f..7204a61 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp @@ -44,7 +44,7 @@ namespace WebCore { -PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::Local<v8::Value> value, bool findOnly) +static PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::Local<v8::Value> value, bool findOnly) { #if ENABLE(WORKERS) WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); @@ -53,8 +53,10 @@ PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::L #endif V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (proxy) - return findOnly ? proxy->FindObjectEventListener(value, false) : proxy->FindOrCreateObjectEventListener(value, false); + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, false) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); + } return PassRefPtr<EventListener>(); } @@ -62,7 +64,7 @@ PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::L ACCESSOR_GETTER(XMLHttpRequestOnabort) { INC_STATS("DOM.XMLHttpRequest.onabort._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onabort()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onabort()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -74,7 +76,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnabort) ACCESSOR_SETTER(XMLHttpRequestOnabort) { INC_STATS("DOM.XMLHttpRequest.onabort._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onabort()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onabort()); @@ -96,7 +98,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnabort) ACCESSOR_GETTER(XMLHttpRequestOnerror) { INC_STATS("DOM.XMLHttpRequest.onerror._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onerror()) { RefPtr<V8ObjectEventListener> listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onerror()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -108,7 +110,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnerror) ACCESSOR_SETTER(XMLHttpRequestOnerror) { INC_STATS("DOM.XMLHttpRequest.onerror._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onerror()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onerror()); @@ -130,7 +132,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnerror) ACCESSOR_GETTER(XMLHttpRequestOnload) { INC_STATS("DOM.XMLHttpRequest.onload._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onload()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onload()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -142,7 +144,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnload) ACCESSOR_SETTER(XMLHttpRequestOnload) { INC_STATS("DOM.XMLHttpRequest.onload._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onload()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onload()); @@ -164,7 +166,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnload) ACCESSOR_GETTER(XMLHttpRequestOnloadstart) { INC_STATS("DOM.XMLHttpRequest.onloadstart._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onloadstart()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onloadstart()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -176,7 +178,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnloadstart) ACCESSOR_SETTER(XMLHttpRequestOnloadstart) { INC_STATS("DOM.XMLHttpRequest.onloadstart._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onloadstart()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onloadstart()); @@ -198,7 +200,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnloadstart) ACCESSOR_GETTER(XMLHttpRequestOnprogress) { INC_STATS("DOM.XMLHttpRequest.onprogress._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onprogress()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onprogress()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -210,7 +212,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnprogress) ACCESSOR_SETTER(XMLHttpRequestOnprogress) { INC_STATS("DOM.XMLHttpRequest.onprogress._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onprogress()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onprogress()); @@ -232,7 +234,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnprogress) ACCESSOR_GETTER(XMLHttpRequestOnreadystatechange) { INC_STATS("DOM.XMLHttpRequest.onreadystatechange._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onreadystatechange()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onreadystatechange()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -244,7 +246,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnreadystatechange) ACCESSOR_SETTER(XMLHttpRequestOnreadystatechange) { INC_STATS("DOM.XMLHttpRequest.onreadystatechange._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onreadystatechange()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onreadystatechange()); @@ -268,14 +270,14 @@ ACCESSOR_GETTER(XMLHttpRequestResponseText) // FIXME: This is only needed because webkit set this getter as custom. // So we need a custom method to avoid forking the IDL file. INC_STATS("DOM.XMLHttpRequest.responsetext._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); return v8StringOrNull(xmlHttpRequest->responseText()); } CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) { INC_STATS("DOM.XMLHttpRequest.addEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, args[1], false); if (listener) { @@ -291,7 +293,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) CALLBACK_FUNC_DECL(XMLHttpRequestRemoveEventListener) { INC_STATS("DOM.XMLHttpRequest.removeEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, args[1], true); if (listener) { @@ -315,9 +317,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOpen) // open(method, url, async, user, passwd) if (args.Length() < 2) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); String method = toWebCoreString(args[0]); String urlstring = toWebCoreString(args[1]); @@ -345,10 +347,10 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOpen) ExceptionCode ec = 0; String user, passwd; if (args.Length() >= 4 && !args[3]->IsUndefined()) { - user = valueToStringWithNullCheck(args[3]); + user = toWebCoreStringWithNullCheck(args[3]); if (args.Length() >= 5 && !args[4]->IsUndefined()) { - passwd = valueToStringWithNullCheck(args[4]); + passwd = toWebCoreStringWithNullCheck(args[4]); xmlHttpRequest->open(method, url, async, user, passwd, ec); } else xmlHttpRequest->open(method, url, async, user, ec); @@ -370,7 +372,7 @@ static bool IsDocumentType(v8::Handle<v8::Value> value) CALLBACK_FUNC_DECL(XMLHttpRequestSend) { INC_STATS("DOM.XMLHttpRequest.send()"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); ExceptionCode ec = 0; if (args.Length() < 1) @@ -380,11 +382,11 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSend) // FIXME: upstream handles "File" objects too. if (IsDocumentType(arg)) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); - Document* document = V8Proxy::DOMWrapperToNode<Document>(object); + Document* document = V8DOMWrapper::convertDOMWrapperToNode<Document>(object); ASSERT(document); xmlHttpRequest->send(document, ec); } else - xmlHttpRequest->send(valueToStringWithNullCheck(arg), ec); + xmlHttpRequest->send(toWebCoreStringWithNullCheck(arg), ec); } if (ec) @@ -396,9 +398,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSend) CALLBACK_FUNC_DECL(XMLHttpRequestSetRequestHeader) { INC_STATS("DOM.XMLHttpRequest.setRequestHeader()"); if (args.Length() < 2) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); ExceptionCode ec = 0; String header = toWebCoreString(args[0]); String value = toWebCoreString(args[1]); @@ -412,9 +414,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestGetResponseHeader) { INC_STATS("DOM.XMLHttpRequest.getResponseHeader()"); if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); ExceptionCode ec = 0; String header = toWebCoreString(args[0]); String result = xmlHttpRequest->getResponseHeader(header, ec); @@ -427,9 +429,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOverrideMimeType) { INC_STATS("DOM.XMLHttpRequest.overrideMimeType()"); if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); String value = toWebCoreString(args[0]); xmlHttpRequest->overrideMimeType(value); return v8::Undefined(); diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp index 7afa82c..bbc69dd 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp @@ -46,7 +46,7 @@ namespace WebCore { ACCESSOR_GETTER(XMLHttpRequestUploadOnabort) { INC_STATS("DOM.XMLHttpRequestUpload.onabort._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onabort()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onabort()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -58,7 +58,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnabort) ACCESSOR_SETTER(XMLHttpRequestUploadOnabort) { INC_STATS("DOM.XMLHttpRequestUpload.onabort._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onabort()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onabort()); @@ -74,7 +74,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnabort) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnabort(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -85,7 +85,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnabort) ACCESSOR_GETTER(XMLHttpRequestUploadOnerror) { INC_STATS("DOM.XMLHttpRequestUpload.onerror._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onerror()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onerror()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -97,7 +97,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnerror) ACCESSOR_SETTER(XMLHttpRequestUploadOnerror) { INC_STATS("DOM.XMLHttpRequestUpload.onerror._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onerror()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onerror()); @@ -113,7 +113,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnerror) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnerror(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -124,7 +124,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnerror) ACCESSOR_GETTER(XMLHttpRequestUploadOnload) { INC_STATS("DOM.XMLHttpRequestUpload.onload._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onload()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onload()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -136,7 +136,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnload) ACCESSOR_SETTER(XMLHttpRequestUploadOnload) { INC_STATS("DOM.XMLHttpRequestUpload.onload._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onload()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onload()); @@ -152,7 +152,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnload) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnload(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -163,7 +163,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnload) ACCESSOR_GETTER(XMLHttpRequestUploadOnloadstart) { INC_STATS("DOM.XMLHttpRequestUpload.onloadstart._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onloadstart()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onloadstart()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -175,7 +175,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnloadstart) ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart) { INC_STATS("DOM.XMLHttpRequestUpload.onloadstart._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onloadstart()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onloadstart()); @@ -191,7 +191,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnloadstart(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -202,7 +202,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart) ACCESSOR_GETTER(XMLHttpRequestUploadOnprogress) { INC_STATS("DOM.XMLHttpRequestUpload.onprogress._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onprogress()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onprogress()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -214,7 +214,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnprogress) ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress) { INC_STATS("DOM.XMLHttpRequestUpload.onprogress._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onprogress()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onprogress()); @@ -230,7 +230,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnprogress(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -241,14 +241,14 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress) CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener) { INC_STATS("DOM.XMLHttpRequestUpload.addEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(args[1], false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), args[1], false); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -262,14 +262,14 @@ CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener) CALLBACK_FUNC_DECL(XMLHttpRequestUploadRemoveEventListener) { INC_STATS("DOM.XMLHttpRequestUpload.removeEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); if (!proxy) return v8::Undefined(); // Probably leaked. - RefPtr<EventListener> listener = proxy->FindObjectEventListener(args[1], false); + RefPtr<EventListener> listener = proxy->objectListeners()->findWrapper(args[1], false); if (listener) { String type = toWebCoreString(args[0]); diff --git a/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp b/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp index 7b20293..dd1c3ad 100644 --- a/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp @@ -39,7 +39,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(XMLSerializerConstructor) { INC_STATS("DOM.XMLSerializer.Constructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::XMLSERIALIZER, XMLSerializer>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::XMLSERIALIZER, XMLSerializer>(args); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp b/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp index 84d75db..69a8635 100644 --- a/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp @@ -39,7 +39,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(XPathEvaluatorConstructor) { INC_STATS("DOM.XPathEvaluator.Constructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::XPATHEVALUATOR, XPathEvaluator>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::XPATHEVALUATOR, XPathEvaluator>(args); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp index d470f84..1ad7d4a 100644 --- a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp @@ -48,7 +48,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(XSLTProcessorConstructor) { INC_STATS("DOM.XSLTProcessor.Constructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::XSLTPROCESSOR, XSLTProcessor>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::XSLTPROCESSOR, XSLTProcessor>(args); } @@ -58,9 +58,9 @@ CALLBACK_FUNC_DECL(XSLTProcessorImportStylesheet) if (!V8Node::HasInstance(args[0])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args[0]); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); imp->importStylesheet(node); return v8::Undefined(); } @@ -72,12 +72,12 @@ CALLBACK_FUNC_DECL(XSLTProcessorTransformToFragment) if (!V8Node::HasInstance(args[0]) || !V8Document::HasInstance(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); - Node* source = V8Proxy::DOMWrapperToNode<Node>(args[0]); - Document* owner = V8Proxy::DOMWrapperToNode<Document>(args[1]); + Node* source = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); + Document* owner = V8DOMWrapper::convertDOMWrapperToNode<Document>(v8::Handle<v8::Object>::Cast(args[1])); RefPtr<DocumentFragment> result = imp->transformToFragment(source, owner); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } @@ -88,9 +88,9 @@ CALLBACK_FUNC_DECL(XSLTProcessorTransformToDocument) if (!V8Node::HasInstance(args[0])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); - Node* source = V8Proxy::DOMWrapperToNode<Node>(args[0]); + Node* source = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); if (!source) return v8::Undefined(); @@ -98,7 +98,7 @@ CALLBACK_FUNC_DECL(XSLTProcessorTransformToDocument) if (!result) return v8::Undefined(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } @@ -108,7 +108,7 @@ CALLBACK_FUNC_DECL(XSLTProcessorSetParameter) if (isUndefinedOrNull(args[1]) || isUndefinedOrNull(args[2])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); @@ -125,7 +125,7 @@ CALLBACK_FUNC_DECL(XSLTProcessorGetParameter) if (isUndefinedOrNull(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); @@ -142,7 +142,7 @@ CALLBACK_FUNC_DECL(XSLTProcessorRemoveParameter) if (isUndefinedOrNull(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); diff --git a/WebCore/bindings/v8/npruntime.cpp b/WebCore/bindings/v8/npruntime.cpp new file mode 100644 index 0000000..64a1927 --- /dev/null +++ b/WebCore/bindings/v8/npruntime.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007-2009 Google, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "NPV8Object.h" +#include "npruntime_impl.h" +#include "npruntime_priv.h" +#include "V8NPObject.h" + +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/Assertions.h> + +// FIXME: Consider removing locks if we're singlethreaded already. +// The static initializer here should work okay, but we want to avoid +// static initialization in general. + +namespace { + +// We use StringKey here as the key-type to avoid a string copy to +// construct the map key and for faster comparisons than strcmp. +class StringKey { +public: + explicit StringKey(const char* str) : m_string(str), m_length(strlen(str)) { } + StringKey() : m_string(0), m_length(0) { } + explicit StringKey(WTF::HashTableDeletedValueType) : m_string(hashTableDeletedValue()), m_length(0) { } + + StringKey& operator=(const StringKey& other) + { + this->m_string = other.m_string; + this->m_length = other.m_length; + return *this; + } + + bool isHashTableDeletedValue() const + { + return m_string == hashTableDeletedValue(); + } + + const char* m_string; + size_t m_length; + +private: + const char* hashTableDeletedValue() const + { + return reinterpret_cast<const char*>(-1); + } +}; + +inline bool operator==(const StringKey& x, const StringKey& y) +{ + if (x.m_length != y.m_length) + return false; + if (x.m_string == y.m_string) + return true; + + ASSERT(!x.isHashTableDeletedValue() && !y.isHashTableDeletedValue()); + return !memcmp(x.m_string, y.m_string, y.m_length); +} + +// Implement WTF::DefaultHash<StringKey>::Hash interface. +struct StringKeyHash { + static unsigned hash(const StringKey& key) + { + // Compute string hash. + unsigned hash = 0; + size_t len = key.m_length; + const char* str = key.m_string; + for (size_t i = 0; i < len; i++) { + char c = str[i]; + hash += c; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + if (hash == 0) + hash = 27; + return hash; + } + + static bool equal(const StringKey& x, const StringKey& y) + { + return x == y; + } + + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +} // namespace + +// Implement HashTraits<StringKey> +struct StringKeyHashTraits : WTF::GenericHashTraits<StringKey> { + static void constructDeletedValue(StringKey& slot) + { + new (&slot) StringKey(WTF::HashTableDeletedValue); + } + + static bool isDeletedValue(const StringKey& value) + { + return value.isHashTableDeletedValue(); + } +}; + +typedef WTF::HashMap<StringKey, PrivateIdentifier*, StringKeyHash, StringKeyHashTraits> StringIdentifierMap; + +static StringIdentifierMap* getStringIdentifierMap() +{ + static StringIdentifierMap* stringIdentifierMap = 0; + if (!stringIdentifierMap) + stringIdentifierMap = new StringIdentifierMap(); + return stringIdentifierMap; +} + +typedef WTF::HashMap<int, PrivateIdentifier*> IntIdentifierMap; + +static IntIdentifierMap* getIntIdentifierMap() +{ + static IntIdentifierMap* intIdentifierMap = 0; + if (!intIdentifierMap) + intIdentifierMap = new IntIdentifierMap(); + return intIdentifierMap; +} + +extern "C" { + +NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name) +{ + ASSERT(name); + + if (name) { + + StringKey key(name); + StringIdentifierMap* identMap = getStringIdentifierMap(); + StringIdentifierMap::iterator iter = identMap->find(key); + if (iter != identMap->end()) + return static_cast<NPIdentifier>(iter->second); + + size_t nameLen = key.m_length; + + // We never release identifiers, so this dictionary will grow. + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(malloc(sizeof(PrivateIdentifier) + nameLen + 1)); + char* nameStorage = reinterpret_cast<char*>(identifier + 1); + memcpy(nameStorage, name, nameLen + 1); + identifier->isString = true; + identifier->value.string = reinterpret_cast<NPUTF8*>(nameStorage); + key.m_string = nameStorage; + identMap->set(key, identifier); + return (NPIdentifier)identifier; + } + + return 0; +} + +void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers) +{ + ASSERT(names); + ASSERT(identifiers); + + if (names && identifiers) { + for (int i = 0; i < nameCount; i++) + identifiers[i] = _NPN_GetStringIdentifier(names[i]); + } +} + +NPIdentifier _NPN_GetIntIdentifier(int32_t intId) +{ + // Special case for -1 and 0, both cannot be used as key in HashMap. + if (!intId || intId == -1) { + static PrivateIdentifier* minusOneOrZeroIds[2]; + PrivateIdentifier* id = minusOneOrZeroIds[intId + 1]; + if (!id) { + id = reinterpret_cast<PrivateIdentifier*>(malloc(sizeof(PrivateIdentifier))); + id->isString = false; + id->value.number = intId; + minusOneOrZeroIds[intId + 1] = id; + } + return (NPIdentifier) id; + } + + IntIdentifierMap* identMap = getIntIdentifierMap(); + IntIdentifierMap::iterator iter = identMap->find(intId); + if (iter != identMap->end()) + return static_cast<NPIdentifier>(iter->second); + + // We never release identifiers, so this dictionary will grow. + PrivateIdentifier* identifier = reinterpret_cast<PrivateIdentifier*>(malloc(sizeof(PrivateIdentifier))); + identifier->isString = false; + identifier->value.number = intId; + identMap->set(intId, identifier); + return (NPIdentifier)identifier; +} + +bool _NPN_IdentifierIsString(NPIdentifier identifier) +{ + PrivateIdentifier* privateIdentifier = reinterpret_cast<PrivateIdentifier*>(identifier); + return privateIdentifier->isString; +} + +NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier) +{ + PrivateIdentifier* privateIdentifier = reinterpret_cast<PrivateIdentifier*>(identifier); + if (!privateIdentifier->isString || !privateIdentifier->value.string) + return 0; + + return (NPUTF8*) strdup(privateIdentifier->value.string); +} + +int32_t _NPN_IntFromIdentifier(NPIdentifier identifier) +{ + PrivateIdentifier* privateIdentifier = reinterpret_cast<PrivateIdentifier*>(identifier); + if (privateIdentifier->isString) + return 0; + return privateIdentifier->value.number; +} + +void _NPN_ReleaseVariantValue(NPVariant* variant) +{ + ASSERT(variant); + + if (variant->type == NPVariantType_Object) { + _NPN_ReleaseObject(variant->value.objectValue); + variant->value.objectValue = 0; + } else if (variant->type == NPVariantType_String) { + free((void*)variant->value.stringValue.UTF8Characters); + variant->value.stringValue.UTF8Characters = 0; + variant->value.stringValue.UTF8Length = 0; + } + + variant->type = NPVariantType_Void; +} + +NPObject *_NPN_CreateObject(NPP npp, NPClass* npClass) +{ + ASSERT(npClass); + + if (npClass) { + NPObject* npObject; + if (npClass->allocate != 0) + npObject = npClass->allocate(npp, npClass); + else + npObject = reinterpret_cast<NPObject*>(malloc(sizeof(NPObject))); + + npObject->_class = npClass; + npObject->referenceCount = 1; + return npObject; + } + + return 0; +} + +NPObject* _NPN_RetainObject(NPObject* npObject) +{ + ASSERT(npObject); + ASSERT(npObject->referenceCount > 0); + + if (npObject) + npObject->referenceCount++; + + return npObject; +} + +// _NPN_DeallocateObject actually deletes the object. Technically, +// callers should use _NPN_ReleaseObject. Webkit exposes this function +// to kill objects which plugins may not have properly released. +void _NPN_DeallocateObject(NPObject* npObject) +{ + ASSERT(npObject); + ASSERT(npObject->referenceCount >= 0); + + if (npObject) { + // NPObjects that remain in pure C++ may never have wrappers. + // Hence, if it's not already alive, don't unregister it. + // If it is alive, unregister it as the *last* thing we do + // so that it can do as much cleanup as possible on its own. + if (_NPN_IsAlive(npObject)) + _NPN_UnregisterObject(npObject); + + npObject->referenceCount = -1; + if (npObject->_class->deallocate) + npObject->_class->deallocate(npObject); + else + free(npObject); + } +} + +void _NPN_ReleaseObject(NPObject* npObject) +{ + ASSERT(npObject); + ASSERT(npObject->referenceCount >= 1); + + if (npObject && npObject->referenceCount >= 1) { + if (!--npObject->referenceCount) + _NPN_DeallocateObject(npObject); + } +} + +void _NPN_InitializeVariantWithStringCopy(NPVariant* variant, const NPString* value) +{ + variant->type = NPVariantType_String; + variant->value.stringValue.UTF8Length = value->UTF8Length; + variant->value.stringValue.UTF8Characters = reinterpret_cast<NPUTF8*>(malloc(sizeof(NPUTF8) * value->UTF8Length)); + memcpy((void*)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length); +} + + +// NPN_Registry +// +// The registry is designed for quick lookup of NPObjects. +// JS needs to be able to quickly lookup a given NPObject to determine +// if it is alive or not. +// The browser needs to be able to quickly lookup all NPObjects which are +// "owned" by an object. +// +// The liveObjectMap is a hash table of all live objects to their owner +// objects. Presence in this table is used primarily to determine if +// objects are live or not. +// +// The rootObjectMap is a hash table of root objects to a set of +// objects that should be deactivated in sync with the root. A +// root is defined as a top-level owner object. This is used on +// Frame teardown to deactivate all objects associated +// with a particular plugin. + +typedef WTF::HashSet<NPObject*> NPObjectSet; +typedef WTF::HashMap<NPObject*, NPObject*> NPObjectMap; +typedef WTF::HashMap<NPObject*, NPObjectSet*> NPRootObjectMap; + +// A map of live NPObjects with pointers to their Roots. +NPObjectMap liveObjectMap; + +// A map of the root objects and the list of NPObjects +// associated with that object. +NPRootObjectMap rootObjectMap; + +void _NPN_RegisterObject(NPObject* npObject, NPObject* owner) +{ + ASSERT(npObject); + + // Check if already registered. + if (liveObjectMap.find(npObject) != liveObjectMap.end()) + return; + + if (!owner) { + // Registering a new owner object. + ASSERT(rootObjectMap.find(npObject) == rootObjectMap.end()); + rootObjectMap.set(npObject, new NPObjectSet()); + } else { + // Always associate this object with it's top-most parent. + // Since we always flatten, we only have to look up one level. + NPObjectMap::iterator ownerEntry = liveObjectMap.find(owner); + NPObject* parent = 0; + if (liveObjectMap.end() != ownerEntry) + parent = ownerEntry->second; + + if (parent) + owner = parent; + ASSERT(rootObjectMap.find(npObject) == rootObjectMap.end()); + if (rootObjectMap.find(owner) != rootObjectMap.end()) + rootObjectMap.get(owner)->add(npObject); + } + + ASSERT(liveObjectMap.find(npObject) == liveObjectMap.end()); + liveObjectMap.set(npObject, owner); +} + +void _NPN_UnregisterObject(NPObject* npObject) +{ + ASSERT(npObject); + ASSERT(liveObjectMap.find(npObject) != liveObjectMap.end()); + + NPObject* owner = 0; + if (liveObjectMap.find(npObject) != liveObjectMap.end()) + owner = liveObjectMap.find(npObject)->second; + + if (!owner) { + // Unregistering a owner object; also unregister it's descendants. + ASSERT(rootObjectMap.find(npObject) != rootObjectMap.end()); + NPObjectSet* set = rootObjectMap.get(npObject); + while (set->size() > 0) { +#ifndef NDEBUG + int size = set->size(); +#endif + NPObject* sub_object = *(set->begin()); + // The sub-object should not be a owner! + ASSERT(rootObjectMap.find(sub_object) == rootObjectMap.end()); + + // First, unregister the object. + set->remove(sub_object); + liveObjectMap.remove(sub_object); + + // Remove the JS references to the object. + forgetV8ObjectForNPObject(sub_object); + + ASSERT(set->size() < size); + } + delete set; + rootObjectMap.remove(npObject); + } else { + NPRootObjectMap::iterator ownerEntry = rootObjectMap.find(owner); + if (ownerEntry != rootObjectMap.end()) { + NPObjectSet* list = ownerEntry->second; + ASSERT(list->find(npObject) != list->end()); + list->remove(npObject); + } + } + + liveObjectMap.remove(npObject); + forgetV8ObjectForNPObject(npObject); +} + +bool _NPN_IsAlive(NPObject* npObject) +{ + return liveObjectMap.find(npObject) != liveObjectMap.end(); +} + +} // extern "C" diff --git a/WebCore/bindings/v8/npruntime_impl.h b/WebCore/bindings/v8/npruntime_impl.h new file mode 100644 index 0000000..31c0f42 --- /dev/null +++ b/WebCore/bindings/v8/npruntime_impl.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2008, 2009, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef npruntime_impl_h +#define npruntime_impl_h + +#include "bindings/npruntime.h" + +// This file exists to support WebCore, which expects to be able to call upon +// portions of the NPRuntime implementation. + +#ifdef __cplusplus +extern "C" { +#endif + +NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name); +void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier*); +NPIdentifier _NPN_GetIntIdentifier(int32_t intId); +bool _NPN_IdentifierIsString(NPIdentifier); +NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier); +int32_t _NPN_IntFromIdentifier(NPIdentifier); +void _NPN_ReleaseVariantValue(NPVariant*); +NPObject *_NPN_CreateObject(NPP, NPClass*); +NPObject* _NPN_RetainObject(NPObject*); +void _NPN_ReleaseObject(NPObject*); +bool _NPN_Invoke(NPP, NPObject*, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result); +bool _NPN_InvokeDefault(NPP, NPObject*, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result); +bool _NPN_Evaluate(NPP, NPObject*, NPString* npScript, NPVariant* result); +bool _NPN_EvaluateHelper(NPP, bool popupsAllowed, NPObject*, NPString* npScript, NPVariant* result); +bool _NPN_GetProperty(NPP, NPObject*, NPIdentifier propertyName, NPVariant* result); +bool _NPN_SetProperty(NPP, NPObject*, NPIdentifier propertyName, const NPVariant* value); +bool _NPN_RemoveProperty(NPP, NPObject*, NPIdentifier propertyName); +bool _NPN_HasProperty(NPP, NPObject*, NPIdentifier propertyName); +bool _NPN_HasMethod(NPP, NPObject*, NPIdentifier methodName); +void _NPN_SetException(NPObject*, const NPUTF8 *message); +bool _NPN_Enumerate(NPP, NPObject*, NPIdentifier**, uint32_t* count); +bool _NPN_Construct(NPP, NPObject*, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif diff --git a/WebCore/bindings/v8/npruntime_internal.h b/WebCore/bindings/v8/npruntime_internal.h new file mode 100644 index 0000000..75bf2b0 --- /dev/null +++ b/WebCore/bindings/v8/npruntime_internal.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007 Collabora, Ltd. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * This is a internal include header for npapi.h + * + * Some of the #defines which are in X11 headers conflict with type and enum + * names in JavaScriptCore and WebCore + * This header #undefs those defines to fix the conflicts + * If you need to include npapi.h or npruntime.h when building on X11, + * include this file instead of the actual npapi.h or npruntime.h + */ + +#include "npapi.h" +#include "npruntime.h" +#include "npfunctions.h" + +#ifdef XP_UNIX + #include <X11/Xresource.h> + + #undef None + #undef Above + #undef Below + #undef Auto + #undef Complex + #undef Status +#endif diff --git a/WebCore/bindings/v8/npruntime_priv.h b/WebCore/bindings/v8/npruntime_priv.h new file mode 100644 index 0000000..3887758 --- /dev/null +++ b/WebCore/bindings/v8/npruntime_priv.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef npruntime_priv_h +#define npruntime_priv_h + +#include "third_party/npapi/bindings/npruntime.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + _NPN_InitializeVariantWithStringCopy() will copy string data. The string data + will be deallocated by calls to NPReleaseVariantValue(). +*/ +void _NPN_InitializeVariantWithStringCopy(NPVariant*, const NPString*); +void _NPN_DeallocateObject(NPObject*); + +// The following routines allow the browser to aggressively cleanup NPObjects +// on a per plugin basis. All NPObjects used through the NPRuntime API should +// be "registered" while they are alive. After an object has been +// deleted, it is possible for Javascript to have a reference to that object +// which has not yet been garbage collected. Javascript access to NPObjects +// will reference this registry to determine if the object is accessible or +// not. + +// Windows introduces an additional complication for objects created by the +// plugin. Plugins load inside of a DLL. Each DLL has it's own heap. If +// the browser unloads the plugin DLL, all objects created within the DLL's +// heap instantly become invalid. Normally, when WebKit drops the reference +// on the top-level plugin object, it tells the plugin manager that the +// plugin can be destroyed, which can unload the DLL. So, we must eliminate +// all pointers to any object ever created by the plugin. + +// We generally associate NPObjects with an owner. The owner of an NPObject +// is an NPObject which, when destroyed, also destroys all objects it owns. +// For example, if an NPAPI plugin creates 10 sub-NPObjects, all 11 objects +// (the NPAPI plugin + its 10 sub-objects) should become inaccessible +// simultaneously. + +// The ownership hierarchy is flat, and not a tree. Imagine the following +// object creation: +// PluginObject +// | +// +-- Creates -----> Object1 +// | +// +-- Creates -----> Object2 +// +// PluginObject will be the "owner" for both Object1 and Object2. + +// Register an NPObject with the runtime. If the owner is NULL, the +// object is treated as an owning object. If owner is not NULL, +// this object will be registered as owned by owner's top-level owner. +void _NPN_RegisterObject(NPObject*, NPObject* owner); + +// Unregister an NPObject with the runtime. If obj is an owning +// object, this call will also unregister all of the owned objects. +void _NPN_UnregisterObject(NPObject*); + +// Check to see if an object is registered with the runtime. +// Return true if registered, false otherwise. +bool _NPN_IsAlive(NPObject*); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // npruntime_priv_h |