diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/bindings')
30 files changed, 2865 insertions, 365 deletions
diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp index b07f201..280ec93 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp index 76db871..398a679 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp index 4f58797..55f0e91 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp @@ -325,10 +325,10 @@ void markActiveObjectsForContext(JSGlobalData& globalData, ScriptExecutionContex 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()) + if (wrapper && !wrapper->marked()) wrapper->mark(); } } @@ -545,7 +545,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/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp index 4fd1139..0eefebe 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/src/3rdparty/webkit/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" @@ -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(); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.h index 6d93196..113344f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.h +++ b/src/3rdparty/webkit/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; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp index b8c30c7..22013eb 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -31,11 +31,14 @@ #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" @@ -58,6 +61,7 @@ #include "Settings.h" #include "WindowFeatures.h" #include <runtime/JSObject.h> +#include <runtime/PrototypeFunction.h> using namespace JSC; @@ -92,6 +96,199 @@ void JSDOMWindow::mark() #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 +297,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)) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.h index 52ef4a0..a0e1b8f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridColumnListCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridColumnListCustom.cpp new file mode 100644 index 0000000..af49df4 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridColumnListCustom.cpp @@ -0,0 +1,49 @@ +/* + * 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" +#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->impl()->itemWithName(propertyName)); +} + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridDataSource.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridDataSource.cpp new file mode 100644 index 0000000..e75b10b --- /dev/null +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridDataSource.cpp @@ -0,0 +1,80 @@ +/* + * 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" +#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 { + +JSDataGridDataSource::JSDataGridDataSource(JSC::JSValue dataSource, Frame* frame) + : m_dataSource(dataSource) + , m_frame(frame) +{ +} + +JSDataGridDataSource::~JSDataGridDataSource() +{ +} + +void JSDataGridDataSource::initialize(HTMLDataGridElement* datagrid) +{ + if (!m_frame->script()->isEnabled()) + return; + + JSLock lock(false); + RefPtr<JSDataGridDataSource> protect(this); + + ExecState* exec = m_frame->script()->globalObject()->globalExec(); + + if (!jsDataSource().isObject()) + return; + + JSValue initializeFunction = jsDataSource().get(exec, Identifier(exec, "initialize")); + CallData callData; + CallType callType = initializeFunction.getCallData(callData); + if (callType == CallTypeNone) + return; + + MarkedArgumentBuffer args; + args.append(toJS(exec, datagrid)); + + JSDOMWindowBase::commonJSGlobalData()->timeoutChecker.start(); + call(exec, initializeFunction, callType, callData, m_dataSource, args); + JSDOMWindowBase::commonJSGlobalData()->timeoutChecker.stop(); + + if (exec->hadException()) + reportCurrentException(exec); +} + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridDataSource.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridDataSource.h new file mode 100644 index 0000000..2537b00 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDataGridDataSource.h @@ -0,0 +1,75 @@ +/* + * 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 + +#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(); } + + virtual void initialize(HTMLDataGridElement*); + +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 // JSDataGridDataSource_h diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp index de6565d..37561af 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/bindings/js/JSDOMStringListCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLDataGridElementCustom.cpp index ac088af..5aa0904 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMStringListCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLDataGridElementCustom.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,27 @@ */ #include "config.h" -#include "JSDOMStringList.h" +#include "JSHTMLDataGridElement.h" -#include "DOMStringList.h" +#include "Document.h" +#include "HTMLDataGridElement.h" +#include "JSDataGridDataSource.h" using namespace JSC; namespace WebCore { -JSValue JSDOMStringList::getByIndex(ExecState* exec, unsigned index) +JSValue JSHTMLDataGridElement::dataSource(ExecState*) const { - return jsString(exec, impl()->item(index)); + DataGridDataSource* dataSource = static_cast<HTMLDataGridElement*>(impl())->dataSource(); + if (dataSource && dataSource->isJSDataGridDataSource()) + return asJSDataGridDataSource(dataSource)->jsDataSource(); + return jsNull(); } -JSValue JSDOMStringList::item(ExecState* exec, const ArgList& args) +void JSHTMLDataGridElement::setDataSource(ExecState*, JSValue value) { - unsigned index = args.at(0).toUInt32(exec); - if (index >= impl()->length()) - return jsNull(); - - return jsString(exec, impl()->item(index)); + static_cast<HTMLDataGridElement*>(impl())->setDataSource(JSDataGridDataSource::create(value, impl()->document()->frame())); } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp index 19aae86..2570bc6 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp index f7f12b9..a99e46c 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/bindings/js/JSHistoryCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHistoryCustom.cpp index 998a364..a3b15e1 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/bindings/js/JSLocationCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSLocationCustom.cpp index 9c5a834..e4f1653 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSLocationCustom.cpp +++ b/src/3rdparty/webkit/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) @@ -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/src/3rdparty/webkit/WebCore/bindings/js/JSMessagePortCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSMessagePortCustom.cpp index f4809ae..bfac375 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSMessagePortCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSMessagePortCustom.cpp @@ -43,9 +43,9 @@ void JSMessagePort::mark() DOMObject::mark(); markIfNotNull(m_impl->onmessage()); - markIfNotNull(m_impl->onclose()); - 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(); @@ -60,14 +60,6 @@ void JSMessagePort::mark() } } -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/src/3rdparty/webkit/WebCore/bindings/js/JSStorageCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSStorageCustom.cpp index bc43d79..2d2d0f8 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSStorageCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSStorageCustom.cpp @@ -64,17 +64,17 @@ 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))); - 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/src/3rdparty/webkit/WebCore/bindings/js/JSWorkerContextCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSWorkerContextCustom.cpp index 6824914..14bbe19 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSWorkerContextCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSWorkerContextCustom.cpp @@ -66,7 +66,7 @@ void JSWorkerContext::mark() } } -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)) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp index e570293..3e59df9 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp +++ b/src/3rdparty/webkit/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,9 +81,14 @@ ScriptController::~ScriptController() ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { + if (!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(); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.h b/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.h index f700cd9..4528495 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/bindings/js/ScriptEventListener.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptEventListener.cpp index 0ce7bca..e5be1d6 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptEventListener.cpp +++ b/src/3rdparty/webkit/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,6 +62,11 @@ 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. @@ -80,6 +86,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/src/3rdparty/webkit/WebCore/bindings/js/ScriptSourceCode.h b/src/3rdparty/webkit/WebCore/bindings/js/ScriptSourceCode.h index 4a2403d..0a16265 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptSourceCode.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptSourceCode.h @@ -53,6 +53,8 @@ public: const JSC::SourceCode& jsSourceCode() const { return m_code; } + const String& source() const { return static_cast<StringSourceProvider*>(m_code.provider())->source(); } + private: JSC::SourceCode m_code; }; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/StringSourceProvider.h b/src/3rdparty/webkit/WebCore/bindings/js/StringSourceProvider.h index ab37a56..89dfa67 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/StringSourceProvider.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/StringSourceProvider.h @@ -40,6 +40,7 @@ namespace WebCore { 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) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp b/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp index dd391bc..bcf107b 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp @@ -110,7 +110,7 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, 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()); + m_workerContext->thread()->workerObjectProxy().reportPendingActivity(m_workerContext->hasPendingActivity()); if (comp.complType() == Normal || comp.complType() == ReturnValue) return comp.value(); diff --git a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGenerator.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGenerator.pm index d217c37..fe145f4 100644 --- a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGenerator.pm +++ b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGenerator.pm @@ -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/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm index 4563018..4f9aa1a 100644 --- a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/src/3rdparty/webkit/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"; @@ -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); } @@ -328,8 +327,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"); } @@ -378,36 +377,38 @@ 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{"JSDOMBinding.h"} = 1; + $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}; @@ -439,13 +440,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 +455,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 +468,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 @@ -508,7 +511,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"}; @@ -620,7 +622,7 @@ 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)); @@ -664,9 +666,9 @@ sub GenerateHeader } 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 +676,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 +743,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); @@ -924,12 +920,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 +941,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"); @@ -1063,13 +1059,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)); @@ -1156,7 +1153,18 @@ sub GenerateImplementation } } 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()))"); + 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, "static_cast<$className*>(asObject(slot.slotBase()))"); if ($codeGenerator->IsSVGAnimatedType($type)) { push(@implContent, " RefPtr<$type> obj = $jsType;\n"); push(@implContent, " return toJS(exec, obj.get(), imp);\n"); @@ -1205,31 +1213,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 +1305,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 +1334,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"); @@ -1348,7 +1363,7 @@ 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"); @@ -1664,7 +1679,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,7 +1693,7 @@ sub NativeToJSValue die "Unknown value for ConvertNullStringTo extended attribute"; } - $implKJSInclude{"JSString.h"} = 1; + $implIncludes{"<runtime/JSString.h>"} = 1; return "jsString(exec, $value)"; } @@ -1964,17 +1979,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 +1999,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; @@ -2057,7 +2076,7 @@ bool ${className}Constructor::getOwnPropertySlot(ExecState* exec, const Identifi EOF - $implKJSInclude{"JSNumberCell.h"} = 1; + $implJSCInclude{"JSNumberCell.h"} = 1; return $implContent; } diff --git a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorObjC.pm index fc265f9..10628b4 100644 --- a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorObjC.pm +++ b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorObjC.pm @@ -1129,7 +1129,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 @@ -1226,7 +1236,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 +1262,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/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm new file mode 100644 index 0000000..088668e --- /dev/null +++ b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -0,0 +1,2191 @@ + +# 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; + +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 0 if $type eq "RGBColor"; + 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 "UndetectableHTMLCollection"; + 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"; +} + +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 $conditional = $dataNode->extendedAttributes->{"Conditional"}; + + # - Add default header template + @headerContent = split("\r", $headerTemplate); + + my $conditionalString; + if ($conditional) { + $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + push(@headerContent, "\n#if ${conditionalString}\n\n"); + } + + 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 $conditional; +} + + +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 = V8Proxy::convertDOMWrapperToNode<$implClassName>(holder); +END + + } else { + push(@implContentDecls, <<END); + $implClassName* imp = V8Proxy::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 = V8Proxy::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 = V8Proxy::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + Frame* frame = window->frame(); + if (frame) { + // 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 V8Proxy::retrieve(frame)->getConstructor(type); + } +END + } + + if ($classIndex eq "WORKERCONTEXT") { + $implIncludes{"WorkerContextExecutionProxy.h"} = 1; + push(@implContentDecls, <<END); + return WorkerContextExecutionProxy::retrieve()->GetConstructor(type); +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 = $codeGenerator->StripModule($attribute->signature->type); + 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 = V8Proxy::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 = V8Proxy::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 = $codeGenerator->StripModule($attribute->signature->type); + + my $getterString; + if ($getterStringUsesImp) { + $getterString = "imp->$getterFunc("; + $getterString .= "ec" if $useExceptions; + $getterString .= ")"; + if (IsRefPtrType($returnType)) { + $implIncludes{"wtf/GetPtr.h"} = 1; + $getterString = "WTF::getPtr(" . $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)) { + $wrapper = "new V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>($getterString, imp_wrapper)"; + } else { + $wrapper = "new V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>(imp, &${implClassName}::$getter, &${implClassName}::$setter)"; + } + } else { + if ($implClassIsAnimatedType) { + $wrapper = "V8SVGDynamicPODTypeWrapperCache<$nativeType, $implClassName>::lookupOrCreateWrapper(imp, &${implClassName}::$getter, &${implClassName}::$setter)"; + } else { + $wrapper = GenerateSVGStaticPodTypeWrapper($returnType, $getterString); + } + } + + push(@implContentDecls, " void* wrapper = $wrapper;\n"); + } elsif ($nativeType ne "RGBColor") { + push(@implContentDecls, " $nativeType v = "); + + push(@implContentDecls, "$getterString;\n"); + + if ($useExceptions) { + push(@implContentDecls, GenerateSetDOMException(" ")); + } + + $result = "v"; + if (IsRefPtrType($returnType)) { + $result = "WTF::getPtr(" . $result . ")"; + } + } else { + # Special case: RGBColor is noncopyable + $result = $getterString; + } + + + if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) { + my $resultObject = $result; + if ($attrIsPodType) { + $resultObject = "wrapper"; + } + + push(@implContentDecls, GenerateSVGContextAssignment($implClassName, $resultObject, " ")); + } + + if ($attrIsPodType) { + my $classIndex = uc($attrType); + push(@implContentDecls, " return V8Proxy::convertToV8Object(V8ClassIndex::$classIndex, wrapper);\n"); + } else { + push(@implContentDecls, " return ".NativeToJSValue($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 = V8Proxy::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 = V8Proxy::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 = $codeGenerator->StripModule($attribute->signature->type); + 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 { + push(@implContentDecls, " imp->set" . WK_ucfirst($attrName) . "(" . $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 = V8Proxy::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::Value> 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::v8ElementEventHandlerAccessorGetter"; + $setter = "V8Custom::v8ElementEventHandlerAccessorSetter"; + } 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})) . "')"; + push(@implContent, <<END); + // $commentInfo + { "$attrName", + $getter, + $setter, + $data, + $accessControl, + static_cast<v8::PropertyAttribute>($propAttr), + $on_proto }, +END + } +} + + +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 $conditional = $dataNode->extendedAttributes->{"Conditional"}; + + @allParents = $codeGenerator->FindParentsRecursively($dataNode); + + # - Add default header template + @implContentHeader = split("\r", $headerTemplate); + + push(@implFixedHeader, + "#include \"config.h\"\n" . + "#include \"V8Proxy.h\"\n" . + "#include \"v8_binding.h\"\n\n" . + "#undef LOG\n\n"); + + my $conditionalString; + if ($conditional) { + $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + push(@implFixedHeader, "\n#if ${conditionalString}\n\n"); + } + + 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 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 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(); + instance->SetInternalFieldCount(2); + 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, attrs, sizeof(attrs)/sizeof(*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(V8Proxy::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, consts, sizeof(consts)/sizeof(*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 $conditional; +} + + +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 = $codeGenerator->StripModule($function->signature->type); + 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 ((IsRefPtrType($returnType) || $returnsListItemPodType) && !$nodeToReturn) { + # We don't use getPtr when $nodeToReturn because that situation is + # special-cased below to return a bool. + $implIncludes{"wtf/GetPtr.h"} = 1; + $functionString = "WTF::getPtr(" . $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 V8Proxy::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 (IsRefPtrType($returnType) || $returnsListItemPodType) { + $implIncludes{"wtf/GetPtr.h"} = 1; + $return = "WTF::getPtr(" . $return . ")"; + } + + # If the return type is a POD type, separate out the wrapper generation + if ($returnsListItemPodType) { + $result .= $indent . "V8SVGPODTypeWrapper<" . $nativeReturnType . ">* wrapper = new "; + $result .= "V8SVGPODTypeWrapperCreatorForList<" . $nativeReturnType . ">($return, imp->associatedAttributeName());\n"; + $return = "wrapper"; + } elsif ($returnsPodType) { + $result .= $indent . "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, $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 V8Proxy::convertToV8Object(V8ClassIndex::$classIndex, wrapper);\n"; + } else { + $result .= $indent . "return " . NativeToJSValue($function->signature, $return) . ";\n"; + } + + return $result; +} + + +# Get the class name used for printing javascript DOM-object wrappers. +sub GetClassName +{ + my $type = shift; + return "HTMLCollection" if $type eq "UndetectableHTMLCollection"; + return $type; +} + + +sub GetNativeTypeFromSignature +{ + my $signature = shift; + my $isParameter = shift; + + my $type = $codeGenerator->StripModule($signature->type); + + 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 "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 "unsigned" if $type eq "RGBColor"; + 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 = $codeGenerator->StripModule($signature->type); + + 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 = $codeGenerator->StripModule($signature->type); + + $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 = $codeGenerator->StripModule($signature->type); + + 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 "ToWebCoreString($value)" if $type eq "AtomicString" or $type eq "DOMUserData"; + if ($type eq "DOMString") { + return "valueToStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"}; + return "valueToStringWithNullOrUndefinedCheck($value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}; + return "ToWebCoreString($value)"; + } + + if ($type eq "NodeFilter") { + return "V8Proxy::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) ? V8Proxy::convertDOMWrapperToNode<Node>($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) ? V8Proxy::convertDOMWrapperToNode<${type}>($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) ? V8Proxy::convertToNativeObject<${implClassName}>(V8ClassIndex::${classIndex}, $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 NativeToJSValue +{ + my $signature = shift; + my $value = shift; + my $type = $codeGenerator->StripModule($signature->type); + my $className= "V8$type"; + + return "v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp"; + return "$value ? v8::True() : v8::False()" if $type eq "boolean"; + 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 "v8::Integer::New($value)" if GetNativeType($type) eq "int"; + + 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 "v8StringOrNull($value)" if $conv eq "Null"; + return "v8StringOrUndefined($value)" if $conv eq "Undefined"; + return "v8StringOrFalse($value)" if $conv eq "False"; + + die "Unknown value for ConvertNullStringTo extended attribute"; + } + 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 "V8Proxy::convertNodeToV8Object($value)"; + } + + if ($type eq "EventTarget" or $type eq "SVGElementInstance") { + return "V8Proxy::convertEventTargetToV8Object($value)"; + } + + if ($type eq "Event") { + return "V8Proxy::convertEventToV8Object($value)"; + } + + if ($type eq "EventListener") { + return "V8Proxy::convertEventListenerToV8Object($value)"; + } + + if ($type eq "RGBColor") { + return "V8Proxy::convertToV8Object(V8ClassIndex::RGBCOLOR, new RGBColor($value))"; + } + + if ($type eq "WorkerContext" or $type eq "WorkerLocation" or $type eq "WorkerNavigator") { + $implIncludes{"WorkerContextExecutionProxy.h"} = 1; + my $classIndex = uc($type); + + return "WorkerContextExecutionProxy::ToV8Object(V8ClassIndex::$classIndex, $value)"; + } + + else { + $implIncludes{"wtf/RefCounted.h"} = 1; + $implIncludes{"wtf/RefPtr.h"} = 1; + my $classIndex = uc($type); + + if (IsPodType($type)) { + $value = GenerateSVGStaticPodTypeWrapper($type, $value); + } + + return "V8Proxy::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 "new V8SVGStaticPODTypeWrapper<$nativeType>($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/src/3rdparty/webkit/WebCore/bindings/scripts/IDLParser.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/IDLParser.pm index de7cf9c..c4cb041 100644 --- a/src/3rdparty/webkit/WebCore/bindings/scripts/IDLParser.pm +++ b/src/3rdparty/webkit/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); |