diff options
Diffstat (limited to 'WebCore/bindings/v8')
138 files changed, 7235 insertions, 3309 deletions
diff --git a/WebCore/bindings/v8/ChildThreadDOMData.h b/WebCore/bindings/v8/ChildThreadDOMData.h index ab90e5b..dfb85e8 100644 --- a/WebCore/bindings/v8/ChildThreadDOMData.h +++ b/WebCore/bindings/v8/ChildThreadDOMData.h @@ -39,7 +39,6 @@ namespace WebCore { class ChildThreadDOMData : public DOMData { public: ChildThreadDOMData(); - virtual ~ChildThreadDOMData() { } DOMDataStore& getStore(); diff --git a/WebCore/bindings/v8/DOMData.cpp b/WebCore/bindings/v8/DOMData.cpp index 07254fe..ec9a938 100644 --- a/WebCore/bindings/v8/DOMData.cpp +++ b/WebCore/bindings/v8/DOMData.cpp @@ -33,6 +33,7 @@ #include "ChildThreadDOMData.h" #include "MainThreadDOMData.h" +#include "WebGLUniformLocation.h" namespace WebCore { @@ -43,22 +44,19 @@ DOMData::DOMData() { } +DOMData::~DOMData() +{ +} + DOMData* DOMData::getCurrent() { if (WTF::isMainThread()) - return getCurrentMainThread(); + return MainThreadDOMData::getCurrent(); DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<ChildThreadDOMData>, childThreadDOMData, ()); return childThreadDOMData; } -DOMData* DOMData::getCurrentMainThread() -{ - ASSERT(WTF::isMainThread()); - DEFINE_STATIC_LOCAL(MainThreadDOMData, mainThreadDOMData, ()); - return &mainThreadDOMData; -} - void DOMData::ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject) { if (m_owningThread == WTF::currentThread()) { diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h index 07e14e5..4947e82 100644 --- a/WebCore/bindings/v8/DOMData.h +++ b/WebCore/bindings/v8/DOMData.h @@ -45,10 +45,9 @@ namespace WebCore { class DOMData : public Noncopyable { public: DOMData(); - virtual ~DOMData() { } + virtual ~DOMData(); static DOMData* getCurrent(); - static DOMData* getCurrentMainThread(); // Caller must be on the main thread. virtual DOMDataStore& getStore() = 0; template<typename T> @@ -85,20 +84,10 @@ namespace WebCore { ThreadIdentifier m_owningThread; }; - // Called when the dead object is not in GC thread's map. Go through all - // thread maps to find the one containing it. Then clear the JS reference - // and push the DOM object into the delayed queue for it to be deref-ed at - // later time from the owning thread. - // - // * This is called when the GC thread is not the owning thread. - // * This can be called on any thread that has GC running. - // * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency. - // template<typename T> void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Handle<v8::Object> v8Object, T* domObject) { - - WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + ASSERT(WTF::isMainThread()); DOMDataList& list = DOMDataStore::allStores(); for (size_t i = 0; i < list.size(); ++i) { DOMDataStore* store = list[i]; @@ -109,7 +98,8 @@ namespace WebCore { if (*wrapper == *v8Object) { // Clear the JS reference. domMap->forgetOnly(domObject); - store->domData()->ensureDeref(V8DOMWrapper::domWrapperType(v8Object), domObject); + ASSERT(store->domData()->owningThread() == WTF::currentThread()); + store->domData()->derefObject(V8DOMWrapper::domWrapperType(v8Object), domObject); } } } diff --git a/WebCore/bindings/v8/DOMObjectsInclude.h b/WebCore/bindings/v8/DOMObjectsInclude.h index 6f36f3b..6ed14be 100644 --- a/WebCore/bindings/v8/DOMObjectsInclude.h +++ b/WebCore/bindings/v8/DOMObjectsInclude.h @@ -31,17 +31,38 @@ #ifndef DOMObjectsInclude_h #define DOMObjectsInclude_h -#include "AbstractWorker.h" +#include "Attr.h" #include "BarInfo.h" +#include "BeforeLoadEvent.h" +#include "WebGLActiveInfo.h" +#include "WebGLArray.h" +#include "WebGLArrayBuffer.h" +#include "WebGLBuffer.h" +#include "WebGLByteArray.h" +#include "WebGLFloatArray.h" +#include "WebGLFramebuffer.h" #include "CanvasGradient.h" +#include "WebGLIntArray.h" +#include "CanvasObject.h" #include "CanvasPattern.h" #include "CanvasPixelArray.h" +#include "WebGLProgram.h" +#include "WebGLRenderbuffer.h" +#include "CanvasRenderingContext.h" #include "CanvasRenderingContext2D.h" +#include "WebGLRenderingContext.h" +#include "WebGLShader.h" +#include "WebGLShortArray.h" +#include "WebGLUnsignedByteArray.h" +#include "WebGLUnsignedIntArray.h" +#include "WebGLUnsignedShortArray.h" #include "CanvasStyle.h" +#include "WebGLTexture.h" #include "CharacterData.h" #include "ClientRect.h" #include "ClientRectList.h" #include "Clipboard.h" +#include "CompositionEvent.h" #include "Console.h" #include "Counter.h" #include "CSSCharsetRule.h" @@ -57,7 +78,6 @@ #include "CSSValueList.h" #include "CSSVariablesDeclaration.h" #include "CSSVariablesRule.h" -#include "Database.h" #include "DocumentType.h" #include "DocumentFragment.h" #include "DOMCoreException.h" @@ -86,7 +106,6 @@ #include "HTMLSelectElement.h" #include "HTMLOptionsCollection.h" #include "ImageData.h" -#include "InspectorBackend.h" #include "KeyboardEvent.h" #include "Location.h" #include "Media.h" @@ -106,6 +125,7 @@ #include "NodeIterator.h" #include "OverflowEvent.h" #include "Page.h" +#include "PageTransitionEvent.h" #include "Plugin.h" #include "PluginArray.h" #include "ProcessingInstruction.h" @@ -118,11 +138,6 @@ #include "ScriptExecutionContext.h" #include "SecurityOrigin.h" #include "Settings.h" -#include "SharedWorker.h" -#include "SharedWorkerContext.h" -#include "SQLTransaction.h" -#include "SQLResultSet.h" -#include "SQLResultSetRowList.h" #include "StyleSheet.h" #include "StyleSheetList.h" #include "TextEvent.h" @@ -135,9 +150,7 @@ #include "V8HTMLElement.h" #include "V8LazyEventListener.h" #include "V8NodeFilterCondition.h" -#include "V8ObjectEventListener.h" #include "ValidityState.h" -#include "VoidCallback.h" #include "WebKitAnimationEvent.h" #include "WebKitCSSKeyframeRule.h" #include "WebKitCSSKeyframesRule.h" @@ -151,16 +164,18 @@ #include "XMLHttpRequestProgressEvent.h" #include "XMLHttpRequestUpload.h" #include "XMLSerializer.h" -#include "XPathException.h" -#include "XPathExpression.h" -#include "XPathNSResolver.h" -#include "XPathResult.h" -#include "XSLTProcessor.h" #if ENABLE(OFFLINE_WEB_APPLICATIONS) #include "DOMApplicationCache.h" #endif +#if ENABLE(DATABASE) +#include "Database.h" +#include "SQLTransaction.h" +#include "SQLResultSet.h" +#include "SQLResultSetRowList.h" +#endif // DATABASE + #if ENABLE(DATAGRID) #include "DataGridColumn.h" #include "DataGridColumnList.h" @@ -171,13 +186,11 @@ #include "StorageEvent.h" #endif // DOM_STORAGE -#if ENABLE(GEOLOCATION) +// GEOLOCATION #include "Coordinates.h" #include "Geolocation.h" #include "Geoposition.h" #include "PositionError.h" -#include "PositionErrorCallback.h" -#endif #if ENABLE(SVG) #include "SVGAngle.h" @@ -215,13 +228,21 @@ #include "V8SVGPODTypeWrapper.h" #endif // SVG +#if PLATFORM(ANDROID) +// TODO: Upstream TOUCH_EVENTS guard. #if ENABLE(TOUCH_EVENTS) #include "Touch.h" #include "TouchList.h" #include "TouchEvent.h" #endif +#endif + +#if ENABLE(WEB_SOCKETS) +#include "WebSocket.h" +#endif #if ENABLE(WORKERS) +#include "AbstractWorker.h" #include "DedicatedWorkerContext.h" #include "Worker.h" #include "WorkerContext.h" @@ -229,10 +250,34 @@ #include "WorkerNavigator.h" #endif // WORKERS +#if ENABLE(SHARED_WORKERS) +#include "SharedWorker.h" +#include "SharedWorkerContext.h" +#endif // SHARED_WORKERS + +#if ENABLE(NOTIFICATIONS) +#include "Notification.h" +#include "NotificationCenter.h" +#endif // NOTIFICATIONS + #if ENABLE(XPATH) #include "XPathEvaluator.h" +#include "XPathException.h" +#include "XPathExpression.h" +#include "XPathNSResolver.h" +#include "XPathResult.h" #endif // XPATH +#if ENABLE(XSLT) +#include "XSLTProcessor.h" +#endif // XSLT + +#if ENABLE(INSPECTOR) +#include "InjectedScriptHost.h" +#include "InspectorBackend.h" +#include "InspectorFrontendHost.h" +#endif // INSPECTOR + namespace WebCore { // A helper class for undetectable document.all diff --git a/WebCore/bindings/v8/DateExtension.cpp b/WebCore/bindings/v8/DateExtension.cpp new file mode 100644 index 0000000..7d8b9be --- /dev/null +++ b/WebCore/bindings/v8/DateExtension.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DateExtension.h" + +#include "V8Proxy.h" +#include "V8HiddenPropertyName.h" + +namespace WebCore { + +DateExtension* DateExtension::extension; + +static const char* dateExtensionName = "v8/DateExtension"; +static const char* dateExtensionScript = + "(function () {" + " var counter;" + " var orig_getTime;" + " function getTimeOverride() {" + " if (++counter > 1000)" + " OnSleepDetected();" + " return orig_getTime.call(this);" + " };" + " function enableSleepDetection(enable) {" + " if (enable) {" + " counter = 0;" + " orig_getTime = Date.prototype.getTime;" + " Date.prototype.getTime = getTimeOverride;" + " } else {" + " Date.prototype.getTime = orig_getTime;" + " }" + " };" + " native function Setup();" + " native function OnSleepDetected();" + " Setup(Date, enableSleepDetection);" + "})()"; + +DateExtension::DateExtension() : v8::Extension(dateExtensionName, dateExtensionScript) +{ +} + +DateExtension* DateExtension::get() +{ + if (!extension) + extension = new DateExtension(); + return extension; +} + +void DateExtension::setAllowSleep(bool allow) +{ + v8::Local<v8::Value> result = V8Proxy::currentContext()->Global()->Get(v8::String::New("Date")); + if (result.IsEmpty()) + return; + + v8::Handle<v8::Object> dateObject = v8::Handle<v8::Object>::Cast(result); + if (dateObject.IsEmpty()) + return; + + v8::Local<v8::Value> sleepFunctionHandle = dateObject->GetHiddenValue(V8HiddenPropertyName::sleepFunction()); + if (sleepFunctionHandle.IsEmpty() || !sleepFunctionHandle->IsFunction()) + return; + + v8::Handle<v8::Value> argv[1]; + argv[0] = v8::String::New(allow ? "false" : "true"); + v8::Handle<v8::Function>::Cast(sleepFunctionHandle)->Call(v8::Object::New(), 1, argv); +} + +v8::Handle<v8::FunctionTemplate> DateExtension::GetNativeFunction(v8::Handle<v8::String> name) +{ + if (name->Equals(v8::String::New("Setup"))) + return v8::FunctionTemplate::New(Setup); + if (name->Equals(v8::String::New("OnSleepDetected"))) + return v8::FunctionTemplate::New(OnSleepDetected); + + return v8::Handle<v8::FunctionTemplate>(); +} + +v8::Handle<v8::Value> DateExtension::Setup(const v8::Arguments& args) +{ + if (args.Length() != 2 || !args[0]->IsObject() || !args[1]->IsFunction()) + return v8::Undefined(); + + v8::Handle<v8::Object> dateObject = v8::Handle<v8::Object>::Cast(args[0]); + v8::Handle<v8::Function> enableSleepDetectionFunction = v8::Handle<v8::Function>::Cast(args[1]); + + dateObject->SetHiddenValue(V8HiddenPropertyName::sleepFunction(), enableSleepDetectionFunction); + return v8::Undefined(); +} + +v8::Handle<v8::Value> DateExtension::OnSleepDetected(const v8::Arguments&) +{ + v8::V8::TerminateExecution(); + return v8::Undefined(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/DateExtension.h b/WebCore/bindings/v8/DateExtension.h new file mode 100644 index 0000000..2bccac4 --- /dev/null +++ b/WebCore/bindings/v8/DateExtension.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DateExtension_h +#define DateExtension_h + +#include <v8.h> + +namespace WebCore { + +// Prevent "sleep" calls in unload handlers. +class DateExtension : public v8::Extension { +public: + static DateExtension* get(); + void setAllowSleep(bool allow); + +private: + DateExtension(); + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(v8::Handle<v8::String>); + static v8::Handle<v8::Value> Setup(const v8::Arguments&); + static v8::Handle<v8::Value> OnSleepDetected(const v8::Arguments&); + + static DateExtension* extension; +}; + +} // namespace WebCore + +#endif // DateExtension_h diff --git a/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp index e52a505..bd2bb7b 100644 --- a/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp +++ b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp @@ -31,19 +31,45 @@ // This source file coalesces the V8 derived sources into a single object file to // reduce bloat and allow us to link release builds on 32-bit Windows. +// Require explicit conversion to AtomicString. This helps catch cases where +// the generated bindings cause an expensive implicit conversion. +#define NO_IMPLICIT_ATOMICSTRING + #include "bindings/V8Attr.cpp" #include "bindings/V8BarInfo.cpp" +#include "bindings/V8BeforeLoadEvent.cpp" +#include "bindings/V8WebGLActiveInfo.cpp" +#include "bindings/V8WebGLArray.cpp" +#include "bindings/V8WebGLArrayBuffer.cpp" +#include "bindings/V8WebGLBuffer.cpp" +#include "bindings/V8WebGLByteArray.cpp" +#include "bindings/V8WebGLFloatArray.cpp" +#include "bindings/V8WebGLFramebuffer.cpp" #include "bindings/V8CanvasGradient.cpp" +#include "bindings/V8WebGLIntArray.cpp" #include "bindings/V8CanvasPattern.cpp" #include "bindings/V8CanvasPixelArray.cpp" +#include "bindings/V8WebGLProgram.cpp" +#include "bindings/V8WebGLRenderbuffer.cpp" +#include "bindings/V8CanvasRenderingContext.cpp" #include "bindings/V8CanvasRenderingContext2D.cpp" +#include "bindings/V8WebGLRenderingContext.cpp" +#include "bindings/V8WebGLShader.cpp" +#include "bindings/V8WebGLShortArray.cpp" +#include "bindings/V8WebGLTexture.cpp" +#include "bindings/V8WebGLUniformLocation.cpp" +#include "bindings/V8WebGLUnsignedByteArray.cpp" +#include "bindings/V8WebGLUnsignedIntArray.cpp" +#include "bindings/V8WebGLUnsignedShortArray.cpp" #include "bindings/V8CDATASection.cpp" #include "bindings/V8CharacterData.cpp" #include "bindings/V8ClientRect.cpp" #include "bindings/V8ClientRectList.cpp" #include "bindings/V8Clipboard.cpp" #include "bindings/V8Comment.cpp" +#include "bindings/V8CompositionEvent.cpp" #include "bindings/V8Console.cpp" +#include "bindings/V8Coordinates.cpp" #include "bindings/V8Counter.cpp" #include "bindings/V8CSSCharsetRule.cpp" #include "bindings/V8CSSFontFaceRule.cpp" @@ -78,8 +104,9 @@ #include "bindings/V8EventException.cpp" #include "bindings/V8File.cpp" #include "bindings/V8FileList.cpp" -#include "bindings/V8History.cpp" #include "bindings/V8Geolocation.cpp" +#include "bindings/V8Geoposition.cpp" +#include "bindings/V8History.cpp" #include "bindings/V8HTMLAllCollection.cpp" #include "bindings/V8HTMLAnchorElement.cpp" #include "bindings/V8HTMLAppletElement.cpp" @@ -150,11 +177,6 @@ #include "bindings/V8HTMLUListElement.cpp" #include "bindings/V8HTMLVideoElement.cpp" #include "bindings/V8ImageData.cpp" -#if PLATFORM(ANDROID) -// No inspector for now -#else -#include "bindings/V8InspectorBackend.cpp" -#endif #include "bindings/V8KeyboardEvent.cpp" #include "bindings/V8Location.cpp" #include "bindings/V8Media.cpp" @@ -174,9 +196,13 @@ #include "bindings/V8NodeIterator.cpp" #include "bindings/V8NodeList.cpp" #include "bindings/V8Notation.cpp" +#include "bindings/V8Notification.cpp" +#include "bindings/V8NotificationCenter.cpp" #include "bindings/V8OverflowEvent.cpp" +#include "bindings/V8PageTransitionEvent.cpp" #include "bindings/V8Plugin.cpp" #include "bindings/V8PluginArray.cpp" +#include "bindings/V8PositionError.cpp" #include "bindings/V8ProcessingInstruction.cpp" #include "bindings/V8ProgressEvent.cpp" #include "bindings/V8Range.cpp" @@ -207,6 +233,18 @@ #include "bindings/V8XMLHttpRequestUpload.cpp" #include "bindings/V8XMLSerializer.cpp" +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "bindings/V8DOMApplicationCache.cpp" +#endif + +#if ENABLE(DOM_STORAGE) +#include "bindings/V8Storage.cpp" +#include "bindings/V8StorageEvent.cpp" +#endif + +#if ENABLE(WEB_SOCKETS) +#include "bindings/V8WebSocket.cpp" +#endif #if ENABLE(DATABASE) #include "bindings/V8Database.cpp" @@ -216,14 +254,18 @@ #include "bindings/V8SQLTransaction.cpp" #endif - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) -#include "bindings/V8DOMApplicationCache.cpp" +#if ENABLE(WORKERS) +#include "bindings/V8AbstractWorker.cpp" +#include "bindings/V8DedicatedWorkerContext.cpp" +#include "bindings/V8Worker.cpp" +#include "bindings/V8WorkerContext.cpp" +#include "bindings/V8WorkerLocation.cpp" +#include "bindings/V8WorkerNavigator.cpp" #endif -#if ENABLE(DOM_STORAGE) -#include "bindings/V8Storage.cpp" -#include "bindings/V8StorageEvent.cpp" +#if ENABLE(SHARED_WORKERS) +#include "bindings/V8SharedWorker.cpp" +#include "bindings/V8SharedWorkerContext.cpp" #endif #if ENABLE(SVG) @@ -250,8 +292,8 @@ #include "bindings/V8SVGCircleElement.cpp" #include "bindings/V8SVGClipPathElement.cpp" #include "bindings/V8SVGColor.cpp" +#include "bindings/V8SVGComponentTransferFunctionElement.cpp" #include "bindings/V8SVGCursorElement.cpp" -#include "bindings/V8SVGDefinitionSrcElement.cpp" #include "bindings/V8SVGDefsElement.cpp" #include "bindings/V8SVGDescElement.cpp" #include "bindings/V8SVGDocument.cpp" @@ -260,6 +302,30 @@ #include "bindings/V8SVGElementInstanceList.cpp" #include "bindings/V8SVGEllipseElement.cpp" #include "bindings/V8SVGException.cpp" +#include "bindings/V8SVGFEBlendElement.cpp" +#include "bindings/V8SVGFEColorMatrixElement.cpp" +#include "bindings/V8SVGFEComponentTransferElement.cpp" +#include "bindings/V8SVGFECompositeElement.cpp" +#include "bindings/V8SVGFEDiffuseLightingElement.cpp" +#include "bindings/V8SVGFEDisplacementMapElement.cpp" +#include "bindings/V8SVGFEDistantLightElement.cpp" +#include "bindings/V8SVGFEFloodElement.cpp" +#include "bindings/V8SVGFEFuncAElement.cpp" +#include "bindings/V8SVGFEFuncBElement.cpp" +#include "bindings/V8SVGFEFuncGElement.cpp" +#include "bindings/V8SVGFEFuncRElement.cpp" +#include "bindings/V8SVGFEGaussianBlurElement.cpp" +#include "bindings/V8SVGFEImageElement.cpp" +#include "bindings/V8SVGFEMergeElement.cpp" +#include "bindings/V8SVGFEMergeNodeElement.cpp" +#include "bindings/V8SVGFEMorphologyElement.cpp" +#include "bindings/V8SVGFEOffsetElement.cpp" +#include "bindings/V8SVGFEPointLightElement.cpp" +#include "bindings/V8SVGFESpecularLightingElement.cpp" +#include "bindings/V8SVGFESpotLightElement.cpp" +#include "bindings/V8SVGFETileElement.cpp" +#include "bindings/V8SVGFETurbulenceElement.cpp" +#include "bindings/V8SVGFilterElement.cpp" #include "bindings/V8SVGFontElement.cpp" #include "bindings/V8SVGFontFaceElement.cpp" #include "bindings/V8SVGFontFaceFormatElement.cpp" @@ -333,22 +399,11 @@ #include "bindings/V8SVGTRefElement.cpp" #include "bindings/V8SVGTSpanElement.cpp" #include "bindings/V8SVGUnitTypes.cpp" -#include "bindings/V8SVGURIReference.cpp" #include "bindings/V8SVGUseElement.cpp" #include "bindings/V8SVGViewElement.cpp" #include "bindings/V8SVGZoomEvent.cpp" #endif -#if ENABLE(WORKERS) -#include "bindings/V8AbstractWorker.cpp" -#include "bindings/V8DedicatedWorkerContext.cpp" -#include "bindings/V8SharedWorker.cpp" -#include "bindings/V8Worker.cpp" -#include "bindings/V8WorkerContext.cpp" -#include "bindings/V8WorkerLocation.cpp" -#include "bindings/V8WorkerNavigator.cpp" -#endif - #if ENABLE(XPATH) #include "bindings/V8XPathEvaluator.cpp" #include "bindings/V8XPathException.cpp" @@ -360,3 +415,9 @@ #if ENABLE(XSLT) #include "bindings/V8XSLTProcessor.cpp" #endif + +#if ENABLE(INSPECTOR) +#include "bindings/V8InjectedScriptHost.cpp" +#include "bindings/V8InspectorBackend.cpp" +#include "bindings/V8InspectorFrontendHost.cpp" +#endif diff --git a/WebCore/bindings/v8/MainThreadDOMData.cpp b/WebCore/bindings/v8/MainThreadDOMData.cpp index ea34444..b1b63bf 100644 --- a/WebCore/bindings/v8/MainThreadDOMData.cpp +++ b/WebCore/bindings/v8/MainThreadDOMData.cpp @@ -39,14 +39,30 @@ MainThreadDOMData::MainThreadDOMData() : m_defaultStore(this) { } + +MainThreadDOMData* MainThreadDOMData::getCurrent() +{ + ASSERT(WTF::isMainThread()); + DEFINE_STATIC_LOCAL(MainThreadDOMData, mainThreadDOMData, ()); + return &mainThreadDOMData; +} -DOMDataStore& MainThreadDOMData::getStore() +DOMDataStore& MainThreadDOMData::getMainThreadStore() { + // This is broken out as a separate non-virtual method from getStore() + // so that it can be inlined by getCurrentMainThreadStore, which is + // a hot spot in Dromaeo DOM tests. ASSERT(WTF::isMainThread()); V8IsolatedWorld* world = V8IsolatedWorld::getEntered(); - if (world) + if (UNLIKELY(world != 0)) return *world->getDOMDataStore(); return m_defaultStore; } +DOMDataStore& MainThreadDOMData::getCurrentMainThreadStore() +{ + return getCurrent()->getMainThreadStore(); +} + + } // namespace WebCore diff --git a/WebCore/bindings/v8/MainThreadDOMData.h b/WebCore/bindings/v8/MainThreadDOMData.h index 5c78cec..e8f99c9 100644 --- a/WebCore/bindings/v8/MainThreadDOMData.h +++ b/WebCore/bindings/v8/MainThreadDOMData.h @@ -38,10 +38,16 @@ namespace WebCore { class MainThreadDOMData : public DOMData { public: - MainThreadDOMData(); - DOMDataStore& getStore(); + static MainThreadDOMData* getCurrent(); // Caller must be on the main thread. + static DOMDataStore& getCurrentMainThreadStore(); + + virtual DOMDataStore& getStore() { return getMainThreadStore(); } + private: + MainThreadDOMData(); + DOMDataStore& getMainThreadStore(); + StaticDOMDataStore m_defaultStore; // Note: The DOMDataStores for isolated world are owned by the world object. }; diff --git a/WebCore/bindings/v8/NPV8Object.cpp b/WebCore/bindings/v8/NPV8Object.cpp index cb2a6c1..69cd303 100644 --- a/WebCore/bindings/v8/NPV8Object.cpp +++ b/WebCore/bindings/v8/NPV8Object.cpp @@ -276,7 +276,7 @@ bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStri filename = "npscript"; WebCore::String script = WebCore::String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length); - v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(filename)), 0); + v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(WebCore::ParsedURLString, filename)), 0); if (v8result.IsEmpty()) return false; @@ -413,8 +413,12 @@ bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) void _NPN_SetException(NPObject* npObject, const NPUTF8 *message) { - if (npObject->_class != npScriptObjectClass) + if (!npObject || npObject->_class != npScriptObjectClass) { + // We won't be able to find a proper scope for this exception, so just throw it. + // This is consistent with JSC, which throws a global exception all the time. + V8Proxy::throwError(V8Proxy::GeneralError, message); return; + } v8::HandleScope handleScope; v8::Handle<v8::Context> context = toV8Context(0, npObject); if (context.IsEmpty()) diff --git a/WebCore/bindings/v8/OwnHandle.h b/WebCore/bindings/v8/OwnHandle.h index 6580674..17c551c 100644 --- a/WebCore/bindings/v8/OwnHandle.h +++ b/WebCore/bindings/v8/OwnHandle.h @@ -45,15 +45,13 @@ namespace WebCore { v8::Handle<T> get() const { return m_handle; } void set(v8::Handle<T> handle) { clear(); m_handle = v8::Persistent<T>::New(handle); } - // FIXME: What if we release a weak handle? Won't the callback do the wrong thing? - v8::Persistent<T> release() { v8::Persistent<T> result = m_handle; m_handle.Clear(); return result; } - void adopt(v8::Persistent<T> handle) { clear(); m_handle = handle; } - // Note: This is clear in the OwnPtr sense, not the v8::Handle sense. void clear() { if (m_handle.IsEmpty()) return; + if (m_handle.IsWeak()) + m_handle.ClearWeak(); m_handle.Dispose(); m_handle.Clear(); } diff --git a/WebCore/bindings/v8/RuntimeEnabledFeatures.cpp b/WebCore/bindings/v8/RuntimeEnabledFeatures.cpp new file mode 100644 index 0000000..cf97b5b --- /dev/null +++ b/WebCore/bindings/v8/RuntimeEnabledFeatures.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "RuntimeEnabledFeatures.h" + +namespace WebCore { + +bool RuntimeEnabledFeatures::isDatabaseEnabled = false; +bool RuntimeEnabledFeatures::isLocalStorageEnabled = true; +bool RuntimeEnabledFeatures::isSessionStorageEnabled = true; +bool RuntimeEnabledFeatures::isNotificationsEnabled = false; +bool RuntimeEnabledFeatures::isApplicationCacheEnabled = false; + +} // namespace WebCore diff --git a/WebCore/bindings/v8/RuntimeEnabledFeatures.h b/WebCore/bindings/v8/RuntimeEnabledFeatures.h new file mode 100644 index 0000000..d8078c5 --- /dev/null +++ b/WebCore/bindings/v8/RuntimeEnabledFeatures.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RuntimeEnabledFeatures_h +#define RuntimeEnabledFeatures_h + +namespace WebCore { + +// A class that stores static enablers for all experimental features +class RuntimeEnabledFeatures { +public: + static void setDatabaseEnabled(bool isEnabled) { isDatabaseEnabled = isEnabled; } + static bool databaseEnabled() { return isDatabaseEnabled; } + + static void setLocalStorageEnabled(bool isEnabled) { isLocalStorageEnabled = isEnabled; } + static bool localStorageEnabled() { return isLocalStorageEnabled; } + + static void setSessionStorageEnabled(bool isEnabled) { isSessionStorageEnabled = isEnabled; } + static bool sessionStorageEnabled() { return isSessionStorageEnabled; } + + static void setNotificationsEnabled(bool isEnabled) { isNotificationsEnabled = isEnabled; } + static bool notificationsEnabled() { return isNotificationsEnabled; } + + static void setApplicationCacheEnabled(bool isEnabled) { isApplicationCacheEnabled = isEnabled; } + static bool applicationCacheEnabled() { return isApplicationCacheEnabled; } + +private: + // Never instantiate. + RuntimeEnabledFeatures() { } + + static bool isDatabaseEnabled; + static bool isLocalStorageEnabled; + static bool isSessionStorageEnabled; + static bool isNotificationsEnabled; + static bool isApplicationCacheEnabled; +}; + +} // namespace WebCore + +#endif // RuntimeEnabledFeatures_h diff --git a/WebCore/bindings/v8/ScheduledAction.cpp b/WebCore/bindings/v8/ScheduledAction.cpp index 44e8a37..4f321cb 100644 --- a/WebCore/bindings/v8/ScheduledAction.cpp +++ b/WebCore/bindings/v8/ScheduledAction.cpp @@ -44,8 +44,9 @@ namespace WebCore { -ScheduledAction::ScheduledAction(v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value> argv[]) - : m_code(String(), KURL(), 0) +ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value> argv[]) + : m_context(context) + , m_code(String(), KURL(), 0) { m_function = v8::Persistent<v8::Function>::New(func); @@ -105,9 +106,8 @@ void ScheduledAction::execute(V8Proxy* proxy) { ASSERT(proxy); - LOCK_V8; v8::HandleScope handleScope; - v8::Local<v8::Context> v8Context = proxy->context(); + v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context.get()); if (v8Context.IsEmpty()) return; // JS may not be enabled. @@ -134,9 +134,8 @@ void ScheduledAction::execute(WorkerContext* workerContext) WorkerScriptController* scriptController = workerContext->script(); if (!m_function.IsEmpty() && m_function->IsFunction()) { - LOCK_V8; v8::HandleScope handleScope; - v8::Local<v8::Context> v8Context = scriptController->proxy()->context(); + v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context.get()); ASSERT(!v8Context.IsEmpty()); v8::Context::Scope scope(v8Context); m_function->Call(v8Context->Global(), m_argc, m_argv); diff --git a/WebCore/bindings/v8/ScheduledAction.h b/WebCore/bindings/v8/ScheduledAction.h index 53694c7..003885f 100644 --- a/WebCore/bindings/v8/ScheduledAction.h +++ b/WebCore/bindings/v8/ScheduledAction.h @@ -31,7 +31,9 @@ #ifndef ScheduledAction_h #define ScheduledAction_h +#include "OwnHandle.h" #include "ScriptSourceCode.h" +#include "V8GCController.h" #include <v8.h> @@ -44,9 +46,10 @@ namespace WebCore { class ScheduledAction { public: - ScheduledAction(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); - explicit ScheduledAction(const WebCore::String& code, const KURL& url = KURL()) - : m_argc(0) + ScheduledAction(v8::Handle<v8::Context>, v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); + explicit ScheduledAction(v8::Handle<v8::Context> context, const WebCore::String& code, const KURL& url = KURL()) + : m_context(context) + , m_argc(0) , m_argv(0) , m_code(code, url) { @@ -61,6 +64,7 @@ namespace WebCore { void execute(WorkerContext*); #endif + OwnHandle<v8::Context> m_context; v8::Persistent<v8::Function> m_function; int m_argc; v8::Persistent<v8::Value>* m_argv; diff --git a/WebCore/bindings/v8/ScriptCallFrame.cpp b/WebCore/bindings/v8/ScriptCallFrame.cpp index ab30862..4c29814 100644 --- a/WebCore/bindings/v8/ScriptCallFrame.cpp +++ b/WebCore/bindings/v8/ScriptCallFrame.cpp @@ -42,7 +42,7 @@ namespace WebCore { ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& urlString, int lineNumber, const v8::Arguments& arguments, unsigned skipArgumentCount) : m_functionName(functionName) - , m_sourceURL(urlString) + , m_sourceURL(ParsedURLString, urlString) , m_lineNumber(lineNumber) { for (int i = 0; i < arguments.Length(); ++i) diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index 8eb9478..d9b2fcf 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -38,8 +38,21 @@ namespace WebCore { -ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount) - : m_lastCaller(String(), V8Proxy::sourceName(), V8Proxy::sourceLineNumber() + 1, arguments, skipArgumentCount) +ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount) { + String sourceName; + int sourceLineNumber; + if (!V8Proxy::sourceName(sourceName)) { + return 0; + } + if (!V8Proxy::sourceLineNumber(sourceLineNumber)) { + return 0; + } + sourceLineNumber += 1; + return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber); +} + +ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber) + : m_lastCaller(String(), sourceName, sourceLineNumber, arguments, skipArgumentCount) , m_scriptState(new ScriptState(V8Proxy::retrieveFrameForCurrentContext())) { } diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index 9f628c8..f6a7e39 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -45,7 +45,7 @@ namespace WebCore { class ScriptCallStack : public Noncopyable { public: - ScriptCallStack(const v8::Arguments&, unsigned skipArgumentCount = 0); + static ScriptCallStack* create(const v8::Arguments&, unsigned skipArgumentCount = 0); ~ScriptCallStack(); const ScriptCallFrame& at(unsigned) const; @@ -55,8 +55,10 @@ namespace WebCore { ScriptState* state() const { return m_scriptState.get(); } private: - OwnPtr<ScriptState> m_scriptState; + ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber); + ScriptCallFrame m_lastCaller; + OwnPtr<ScriptState> m_scriptState; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index 48c5115..5b4dbc2 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -45,6 +45,7 @@ #include "EventListener.h" #include "EventNames.h" #include "Frame.h" +#include "FrameLoaderClient.h" #include "Node.h" #include "NotImplemented.h" #include "npruntime_impl.h" @@ -52,15 +53,25 @@ #include "NPV8Object.h" #include "ScriptSourceCode.h" #include "ScriptState.h" -#include "Widget.h" -#include "XSSAuditor.h" - +#include "Settings.h" #include "V8Binding.h" #include "V8NPObject.h" #include "V8Proxy.h" +#include "Widget.h" +#include "XSSAuditor.h" +#include <wtf/StdLibExtras.h> namespace WebCore { +void ScriptController::initializeThreading() +{ + static bool initializedThreading = false; + if (!initializedThreading) { + WTF::initializeThreading(); + initializedThreading = true; + } +} + void ScriptController::setFlags(const char* string, int length) { v8::V8::SetFlagsFromString(string, length); @@ -94,9 +105,9 @@ void ScriptController::gcUnprotectJSWrapper(void* domObject) ScriptController::ScriptController(Frame* frame) : m_frame(frame) , m_sourceURL(0) + , m_inExecuteScript(false) , m_processingTimerCallback(false) , m_paused(false) - , m_scriptState(new ScriptState(frame)) , m_proxy(new V8Proxy(frame)) #if ENABLE(NETSCAPE_PLUGIN_API) , m_windowScriptNPObject(0) @@ -148,7 +159,7 @@ bool ScriptController::processingUserGesture() const return true; V8Proxy* activeProxy = activeFrame->script()->proxy(); - LOCK_V8; + v8::HandleScope handleScope; v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(activeFrame); // FIXME: find all cases context can be empty: @@ -166,6 +177,9 @@ bool ScriptController::processingUserGesture() const // Based on code from kjs_bindings.cpp. // Note: This is more liberal than Firefox's implementation. if (event) { + if (event->createdByDOM()) + return false; + const AtomicString& type = event->type(); bool eventOk = // mouse events @@ -186,9 +200,14 @@ bool ScriptController::processingUserGesture() const return false; } -void ScriptController::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup) +void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources) +{ + m_proxy->evaluateInIsolatedWorld(worldID, sources, 0); +} + +void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup) { - m_proxy->evaluateInNewWorld(sources, extensionGroup); + m_proxy->evaluateInIsolatedWorld(worldID, sources, extensionGroup); } void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) @@ -199,15 +218,9 @@ void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sour // Evaluate a script file in the environment of this proxy. ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { - LOCK_V8; String sourceURL = sourceCode.url(); - if (sourceURL.isNull() && !m_XSSAuditor->canEvaluateJavaScriptURL(sourceCode.source())) { - // This JavaScript URL is not safe to be evaluated. - return ScriptValue(); - } - - if (!sourceURL.isNull() && !m_XSSAuditor->canEvaluate(sourceCode.source())) { + if (!m_XSSAuditor->canEvaluate(sourceCode.source())) { // This script is not safe to be evaluated. return ScriptValue(); } @@ -246,7 +259,6 @@ void ScriptController::finishedWithEvent(Event* event) // Create a V8 object with an interceptor of NPObjectPropertyGetter. void ScriptController::bindToWindowObject(Frame* frame, const String& key, NPObject* object) { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); @@ -264,13 +276,13 @@ void ScriptController::bindToWindowObject(Frame* frame, const String& key, NPObj void ScriptController::collectGarbage() { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_proxy->frame()); if (v8Context.IsEmpty()) return; v8::Context::Scope scope(v8Context); + m_proxy->evaluate(ScriptSourceCode("if (window.gc) void(gc());"), 0); } @@ -286,7 +298,8 @@ bool ScriptController::haveInterpreter() const bool ScriptController::isEnabled() const { - return m_proxy->isEnabled(); + Settings* settings = m_proxy->frame()->settings(); + return m_proxy->frame()->loader()->client()->allowJavaScript(settings && settings->isJavaScriptEnabled() && !m_frame->loader()->isSandboxed(SandboxScripts)); } PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widget) @@ -343,7 +356,7 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge return V8ScriptInstance::create(wrapper); } -void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) +void ScriptController::cleanupScriptObjectsForPlugin(Widget* nativeHandle) { PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle); if (it == m_pluginObjects.end()) @@ -353,6 +366,18 @@ void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) m_pluginObjects.remove(it); } +void ScriptController::getAllWorlds(Vector<DOMWrapperWorld*>& worlds) +{ + worlds.append(mainThreadNormalWorld()); +} + +ScriptState* ScriptController::mainWorldScriptState() +{ + if (!m_mainWorldScriptState) + m_mainWorldScriptState.set(new ScriptState(m_frame, V8Proxy::mainWorldContext(m_frame))); + return m_mainWorldScriptState.get(); +} + static NPObject* createNoScriptObject() { notImplemented(); @@ -361,7 +386,6 @@ static NPObject* createNoScriptObject() static NPObject* createScriptObject(Frame* frame) { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); if (v8Context.IsEmpty()) @@ -399,7 +423,6 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement if (!isEnabled()) return createNoScriptObject(); - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); if (v8Context.IsEmpty()) diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index d614619..fb7bbee 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -39,9 +39,11 @@ #include <v8.h> #include <wtf/HashMap.h> +#include <wtf/RefCounted.h> #include <wtf/Vector.h> namespace WebCore { + class DOMWrapperWorld; class Event; class Frame; class HTMLPlugInElement; @@ -60,16 +62,33 @@ namespace WebCore { // or this accessor should be made JSProxy* V8Proxy* proxy() { return m_proxy.get(); } + ScriptValue executeScript(const ScriptSourceCode&); + ScriptValue executeScript(const String& script, bool forceUserGesture = false); + + // Returns true if argument is a JavaScript URL. + bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, bool replaceDocument = true); + + // This function must be called from the main thread. It is safe to call it repeatedly. + static void initializeThreading(); + // Evaluate a script file in the environment of this proxy. // If succeeded, 'succ' is set to true and result is returned // as a string. ScriptValue evaluate(const ScriptSourceCode&); - // Executes JavaScript in a new world associated with the web frame. The - // script gets its own global scope, its own prototypes for intrinsic - // JavaScript objects (String, Array, and so-on), and its own wrappers for - // all DOM nodes and DOM constructors. - void evaluateInNewWorld(const Vector<ScriptSourceCode>&, int extensionGroup); + void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&); + + // Executes JavaScript in an isolated world. The script gets its own global scope, + // its own prototypes for intrinsic JavaScript objects (String, Array, and so-on), + // and its own wrappers for all DOM nodes and DOM constructors. + // + // If an isolated world with the specified ID already exists, it is reused. + // Otherwise, a new world is created. + // + // If the worldID is 0, a new world is always created. + // + // FIXME: Get rid of extensionGroup here. + void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&, int extensionGroup); // Executes JavaScript in a new context associated with the web frame. The // script gets its own global scope and its own prototypes for intrinsic @@ -77,16 +96,11 @@ namespace WebCore { // all DOM nodes and DOM constructors. void evaluateInNewContext(const Vector<ScriptSourceCode>&, int extensionGroup); - // JSC has a WindowShell object, but for V8, the ScriptController - // is the WindowShell. - bool haveWindowShell() const { return true; } - // Masquerade 'this' as the windowShell. // This is a bit of a hack, but provides reasonable compatibility // with what JSC does as well. - ScriptController* windowShell() { return this; } - - ScriptState* state() const { return m_scriptState.get(); } + ScriptController* windowShell(DOMWrapperWorld*) { return this; } + ScriptController* existingWindowShell(DOMWrapperWorld*) { return this; } XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); } @@ -146,23 +160,31 @@ namespace WebCore { void updateSecurityOrigin(); void clearScriptObjects(); void updatePlatformScriptObjects(); - void cleanupScriptObjectsForPlugin(void*); + void cleanupScriptObjectsForPlugin(Widget*); #if ENABLE(NETSCAPE_PLUGIN_API) NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*); NPObject* windowScriptNPObject(); #endif + // Dummy method to avoid a bunch of ifdef's in WebCore. + void evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*) { } + static void getAllWorlds(Vector<DOMWrapperWorld*>& worlds); + + // Script state for the main world context. + ScriptState* mainWorldScriptState(); + private: Frame* m_frame; const String* m_sourceURL; + bool m_inExecuteScript; + bool m_processingTimerCallback; bool m_paused; - OwnPtr<ScriptState> m_scriptState; OwnPtr<V8Proxy> m_proxy; - typedef HashMap<void*, NPObject*> PluginObjectMap; + typedef HashMap<Widget*, NPObject*> PluginObjectMap; // A mapping between Widgets and their corresponding script object. // This list is used so that when the plugin dies, we can immediately @@ -174,6 +196,9 @@ namespace WebCore { #endif // The XSSAuditor associated with this ScriptController. OwnPtr<XSSAuditor> m_XSSAuditor; + + // Script state for the main world context. + OwnPtr<ScriptState> m_mainWorldScriptState; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptEventListener.cpp b/WebCore/bindings/v8/ScriptEventListener.cpp index 7a8aa64..51d53ab 100644 --- a/WebCore/bindings/v8/ScriptEventListener.cpp +++ b/WebCore/bindings/v8/ScriptEventListener.cpp @@ -33,7 +33,12 @@ #include "Attribute.h" #include "Document.h" +#include "EventListener.h" #include "Frame.h" +#include "ScriptScope.h" +#include "Tokenizer.h" +#include "V8AbstractEventListener.h" +#include "V8Binding.h" #include "XSSAuditor.h" namespace WebCore { @@ -41,18 +46,29 @@ namespace WebCore { PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, Attribute* attr) { ASSERT(node); + int lineNumber = 1; + int columnNumber = 0; + String sourceURL; - Frame* frame = node->document()->frame(); + if (Frame* frame = node->document()->frame()) { + ScriptController* scriptController = frame->script(); + if (!scriptController->isEnabled()) + return 0; - if (!frame) - return 0; + if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { + // This script is not safe to execute. + return 0; + } - if (!frame->script()->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { - // This script is not safe to execute. - return 0; + if (frame->document()->tokenizer()) { + // FIXME: Change to use script->eventHandlerLineNumber() when implemented. + lineNumber = frame->document()->tokenizer()->lineNumber(); + columnNumber = frame->document()->tokenizer()->columnNumber(); + } + sourceURL = node->document()->url().string(); } - return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), node->isSVGElement()); + return V8LazyEventListener::create(attr->localName().string(), node->isSVGElement(), attr->value(), sourceURL, lineNumber, columnNumber, WorldContextHandle(UseMainWorld)); } PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attribute* attr) @@ -60,12 +76,40 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attri if (!frame) return 0; - if (!frame->script()->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { + int lineNumber = 1; + int columnNumber = 0; + String sourceURL; + + 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; } - return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), frame->document()->isSVGDocument()); + if (frame->document()->tokenizer()) { + // FIXME: Change to use script->eventHandlerLineNumber() when implemented. + lineNumber = frame->document()->tokenizer()->lineNumber(); + columnNumber = frame->document()->tokenizer()->columnNumber(); + } + sourceURL = frame->document()->url().string(); + return V8LazyEventListener::create(attr->localName().string(), frame->document()->isSVGDocument(), attr->value(), sourceURL, lineNumber, columnNumber, WorldContextHandle(UseMainWorld)); +} + +String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* listener) +{ + if (listener->type() != EventListener::JSEventListenerType) + return ""; + + ScriptScope scope(scriptState); + V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); + v8::Handle<v8::Object> function = v8Listener->getListenerObject(context); + if (function.IsEmpty()) + return ""; + + return toWebCoreStringWithNullCheck(function); } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptEventListener.h b/WebCore/bindings/v8/ScriptEventListener.h index 0171120..ce12a53 100644 --- a/WebCore/bindings/v8/ScriptEventListener.h +++ b/WebCore/bindings/v8/ScriptEventListener.h @@ -38,11 +38,14 @@ namespace WebCore { class Attribute; + class EventListener; class Frame; class Node; + class ScriptState; PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node*, Attribute*); PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame*, Attribute*); + String getEventListenerHandlerBody(ScriptExecutionContext*, ScriptState*, EventListener*); } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptFunctionCall.cpp b/WebCore/bindings/v8/ScriptFunctionCall.cpp index 2fa43d5..a232acd 100644 --- a/WebCore/bindings/v8/ScriptFunctionCall.cpp +++ b/WebCore/bindings/v8/ScriptFunctionCall.cpp @@ -31,8 +31,6 @@ #include "config.h" #include "ScriptFunctionCall.h" -#include "Document.h" -#include "Frame.h" #include "ScriptScope.h" #include "ScriptState.h" #include "ScriptString.h" @@ -40,19 +38,13 @@ #include "V8Binding.h" #include "V8Proxy.h" +#include "V8Utilities.h" #include <v8.h> #include <wtf/OwnArrayPtr.h> namespace WebCore { -static void reportException(ScriptState* scriptState, v8::TryCatch &exceptionCatcher) -{ - v8::Local<v8::Message> message = exceptionCatcher.Message(); - scriptState->frame()->document()->reportException(toWebCoreString(message->Get()), message->GetLineNumber(), toWebCoreString(message->GetScriptResourceName())); - exceptionCatcher.Reset(); -} - ScriptFunctionCall::ScriptFunctionCall(ScriptState* scriptState, const ScriptObject& thisObject, const String& name) : m_scriptState(scriptState) , m_thisObject(thisObject) @@ -82,6 +74,18 @@ void ScriptFunctionCall::appendArgument(const String& argument) m_arguments.append(v8String(argument)); } +void ScriptFunctionCall::appendArgument(const char* argument) +{ + ScriptScope scope(m_scriptState); + m_arguments.append(v8String(argument)); +} + +void ScriptFunctionCall::appendArgument(long argument) +{ + ScriptScope scope(m_scriptState); + m_arguments.append(v8::Number::New(argument)); +} + void ScriptFunctionCall::appendArgument(long long argument) { ScriptScope scope(m_scriptState); @@ -94,6 +98,12 @@ void ScriptFunctionCall::appendArgument(unsigned int argument) m_arguments.append(v8::Number::New(argument)); } +void ScriptFunctionCall::appendArgument(unsigned long argument) +{ + ScriptScope scope(m_scriptState); + m_arguments.append(v8::Number::New(argument)); +} + void ScriptFunctionCall::appendArgument(int argument) { ScriptScope scope(m_scriptState); diff --git a/WebCore/bindings/v8/ScriptFunctionCall.h b/WebCore/bindings/v8/ScriptFunctionCall.h index 8365a4e..6203402 100644 --- a/WebCore/bindings/v8/ScriptFunctionCall.h +++ b/WebCore/bindings/v8/ScriptFunctionCall.h @@ -50,8 +50,11 @@ namespace WebCore { void appendArgument(const ScriptString&); void appendArgument(const ScriptValue&); void appendArgument(const String&); + void appendArgument(const char*); + void appendArgument(long); void appendArgument(long long); void appendArgument(unsigned int); + void appendArgument(unsigned long); void appendArgument(int); void appendArgument(bool); ScriptValue call(bool& hadException, bool reportExceptions = true); diff --git a/WebCore/bindings/v8/ScriptObject.cpp b/WebCore/bindings/v8/ScriptObject.cpp index b6943bd..5f5609c 100644 --- a/WebCore/bindings/v8/ScriptObject.cpp +++ b/WebCore/bindings/v8/ScriptObject.cpp @@ -36,6 +36,8 @@ #include "Document.h" #include "Frame.h" +#include "InspectorBackend.h" +#include "InspectorFrontendHost.h" #include "V8Binding.h" #include "V8Proxy.h" @@ -83,6 +85,13 @@ bool ScriptObject::set(const char* name, double value) return scope.success(); } +bool ScriptObject::set(const char* name, long value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::String::New(name), v8::Number::New(value)); + return scope.success(); +} + bool ScriptObject::set(const char* name, long long value) { ScriptScope scope(m_scriptState); @@ -97,6 +106,20 @@ bool ScriptObject::set(const char* name, int value) return scope.success(); } +bool ScriptObject::set(const char* name, unsigned value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::String::New(name), v8::Number::New(value)); + return scope.success(); +} + +bool ScriptObject::set(const char* name, unsigned long value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::String::New(name), v8::Number::New(value)); + return scope.success(); +} + bool ScriptObject::set(const char* name, bool value) { ScriptScope scope(m_scriptState); @@ -117,6 +140,7 @@ bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, const S return scope.success(); } +#if ENABLE(INSPECTOR) bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorBackend* value) { ScriptScope scope(scriptState); @@ -126,6 +150,21 @@ bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, Inspect return scope.success(); } +bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorFrontendHost* value) +{ + ScriptScope scope(scriptState); + scope.global()->Set(v8::String::New(name), V8DOMWrapper::convertToV8Object(V8ClassIndex::INSPECTORFRONTENDHOST, value)); + return scope.success(); +} + +bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InjectedScriptHost* value) +{ + ScriptScope scope(scriptState); + scope.global()->Set(v8::String::New(name), V8DOMWrapper::convertToV8Object(V8ClassIndex::INJECTEDSCRIPTHOST, value)); + return scope.success(); +} +#endif + bool ScriptGlobalObject::get(ScriptState* scriptState, const char* name, ScriptObject& value) { ScriptScope scope(scriptState); diff --git a/WebCore/bindings/v8/ScriptObject.h b/WebCore/bindings/v8/ScriptObject.h index dcee3a5..630d3b9 100644 --- a/WebCore/bindings/v8/ScriptObject.h +++ b/WebCore/bindings/v8/ScriptObject.h @@ -36,7 +36,9 @@ #include <v8.h> namespace WebCore { + class InjectedScriptHost; class InspectorBackend; + class InspectorFrontendHost; class ScriptState; class ScriptObject : public ScriptValue { @@ -51,8 +53,11 @@ namespace WebCore { bool set(const char* name, const ScriptObject&); bool set(const char* name, const String&); bool set(const char* name, double); + bool set(const char* name, long); bool set(const char* name, long long); bool set(const char* name, int); + bool set(const char* name, unsigned); + bool set(const char* name, unsigned long); bool set(const char* name, bool); static ScriptObject createNew(ScriptState*); @@ -64,6 +69,8 @@ namespace WebCore { public: static bool set(ScriptState*, const char* name, const ScriptObject&); static bool set(ScriptState*, const char* name, InspectorBackend*); + static bool set(ScriptState*, const char* name, InspectorFrontendHost*); + static bool set(ScriptState*, const char* name, InjectedScriptHost*); static bool get(ScriptState*, const char* name, ScriptObject&); static bool remove(ScriptState*, const char* name); private: diff --git a/WebCore/bindings/v8/ScriptObjectQuarantine.cpp b/WebCore/bindings/v8/ScriptObjectQuarantine.cpp deleted file mode 100644 index 053cf68..0000000 --- a/WebCore/bindings/v8/ScriptObjectQuarantine.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ScriptObjectQuarantine.h" - -#include "Database.h" -#include "Document.h" -#include "DOMWindow.h" -#include "Frame.h" -#include "Page.h" -#include "ScriptObject.h" -#include "ScriptValue.h" - -#include "V8Binding.h" -#include "V8Proxy.h" - -#include <v8.h> - -namespace WebCore { - -ScriptValue quarantineValue(ScriptState* scriptState, const ScriptValue& value) -{ - return value; -} - -bool getQuarantinedScriptObject(Database* database, ScriptObject& quarantinedObject) -{ - ASSERT(database); - - // FIXME: Implement when Database V8 bindings are enabled - ASSERT_NOT_REACHED(); - quarantinedObject = ScriptObject(); - return false; -} - -bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& quarantinedObject) -{ - ASSERT(frame); - ASSERT(storage); - -#if ENABLE(DOM_STORAGE) - v8::HandleScope handleScope; - v8::Local<v8::Context> context = V8Proxy::context(frame); - // FIXME: What if context.IsEmpty()? - v8::Context::Scope scope(context); - - v8::Handle<v8::Value> v8Storage = V8DOMWrapper::convertToV8Object(V8ClassIndex::STORAGE, storage); - quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8Storage))); -#else - ASSERT_NOT_REACHED(); - quarantinedObject = ScriptObject(); -#endif - return true; -} - -bool getQuarantinedScriptObject(Node* node, ScriptObject& quarantinedObject) -{ - ASSERT(node); - - v8::HandleScope handleScope; - // FIXME: What if document() is null? - // FIXME: Why are we grabbing the mainFrame? - Frame* frame = node->document()->page()->mainFrame(); - v8::Local<v8::Context> context = V8Proxy::context(frame); - // FIXME: What if context.IsEmpty()? - v8::Context::Scope scope(context); - - v8::Handle<v8::Value> v8Node = V8DOMWrapper::convertNodeToV8Object(node); - quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8Node))); - - return true; -} - -bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedObject) -{ - ASSERT(domWindow); - - v8::HandleScope handleScope; - Frame* frame = domWindow->frame(); - // FIXME: What if frame is null? - v8::Local<v8::Context> context = V8Proxy::context(frame); - // FIXME: What if context.IsEmpty()? - v8::Context::Scope scope(context); - - v8::Handle<v8::Value> v8DomWindow = V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow); - quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8DomWindow))); - - return true; -} - - -} // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptScope.cpp b/WebCore/bindings/v8/ScriptScope.cpp index 52cab10..727ab25 100644 --- a/WebCore/bindings/v8/ScriptScope.cpp +++ b/WebCore/bindings/v8/ScriptScope.cpp @@ -36,14 +36,13 @@ #include "Document.h" #include "Frame.h" #include "V8Binding.h" -#include "V8Proxy.h" #include <v8.h> namespace WebCore { ScriptScope::ScriptScope(ScriptState* scriptState, bool reportExceptions) - : m_context(V8Proxy::context(scriptState->frame())) + : m_context(scriptState->context()) , m_scope(m_context) , m_scriptState(scriptState) , m_reportExceptions(reportExceptions) diff --git a/WebCore/bindings/v8/ScriptSourceCode.h b/WebCore/bindings/v8/ScriptSourceCode.h index fea387a..5c16168 100644 --- a/WebCore/bindings/v8/ScriptSourceCode.h +++ b/WebCore/bindings/v8/ScriptSourceCode.h @@ -50,7 +50,7 @@ public: // Not sure if that matters. ScriptSourceCode(CachedScript* cs) : m_source(cs->script()) - , m_url(cs->url()) + , m_url(ParsedURLString, cs->url()) , m_startLine(1) { } diff --git a/WebCore/bindings/v8/ScriptState.cpp b/WebCore/bindings/v8/ScriptState.cpp index b9e240c..68593e7 100644 --- a/WebCore/bindings/v8/ScriptState.cpp +++ b/WebCore/bindings/v8/ScriptState.cpp @@ -37,15 +37,29 @@ #include "ScriptController.h" #include <wtf/Assertions.h> +#include <wtf/StdLibExtras.h> namespace WebCore { ScriptState::ScriptState(Frame* frame) : m_frame(frame) + , m_context(v8::Persistent<v8::Context>::New(V8Proxy::mainWorldContext(frame))) { } -ScriptState* scriptStateFromNode(Node* node) +ScriptState::ScriptState(Frame* frame, v8::Handle<v8::Context> context) + : m_frame(frame) + , m_context(v8::Persistent<v8::Context>::New(context)) +{ +} + +ScriptState::~ScriptState() +{ + m_context.Dispose(); + m_context.Clear(); +} + +ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node* node) { // This should be never reached with V8 bindings (WebKit only uses it // for non-JS bindings) @@ -53,9 +67,17 @@ ScriptState* scriptStateFromNode(Node* node) return 0; } -ScriptState* scriptStateFromPage(Page* page) +ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page* page) +{ + // This should be only reached with V8 bindings from single process layout tests. + return page->mainFrame()->script()->mainWorldScriptState(); +} + +// FIXME: Stub method so we compile. Currently called from FrameLoader.cpp. +DOMWrapperWorld* mainThreadNormalWorld() { - return page->mainFrame()->script()->state(); + DEFINE_STATIC_LOCAL(DOMWrapperWorld, oneWorld, ()); + return &oneWorld; } } diff --git a/WebCore/bindings/v8/ScriptState.h b/WebCore/bindings/v8/ScriptState.h index 8fbcfa3..12a1388 100644 --- a/WebCore/bindings/v8/ScriptState.h +++ b/WebCore/bindings/v8/ScriptState.h @@ -32,16 +32,21 @@ #define ScriptState_h #include <v8.h> +#include <wtf/Noncopyable.h> +#include <wtf/RefCounted.h> namespace WebCore { + class DOMWrapperWorld; class Node; class Page; class Frame; - class ScriptState { + class ScriptState : public Noncopyable { public: ScriptState() { } ScriptState(Frame* frame); + ScriptState(Frame* frame, v8::Handle<v8::Context> context); + ~ScriptState(); bool hadException() { return !m_exception.IsEmpty(); } void setException(v8::Local<v8::Value> exception) @@ -51,14 +56,28 @@ namespace WebCore { v8::Local<v8::Value> exception() { return m_exception; } Frame* frame() const { return m_frame; } + v8::Local<v8::Context> context() const + { + return v8::Local<v8::Context>::New(m_context); + } private: v8::Local<v8::Value> m_exception; Frame* m_frame; + v8::Persistent<v8::Context> m_context; + }; + + ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); + ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); + + DOMWrapperWorld* mainThreadNormalWorld(); + inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } + inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } + + // Dummy class to avoid a bunch of ifdef's in WebCore. + class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { }; - ScriptState* scriptStateFromNode(Node*); - ScriptState* scriptStateFromPage(Page*); } #endif // ScriptState_h diff --git a/WebCore/bindings/v8/ScriptString.h b/WebCore/bindings/v8/ScriptString.h index fe254a5..414818a 100644 --- a/WebCore/bindings/v8/ScriptString.h +++ b/WebCore/bindings/v8/ScriptString.h @@ -32,34 +32,41 @@ #define ScriptString_h #include "PlatformString.h" +#include "ScriptStringImpl.h" +#include "V8Binding.h" namespace WebCore { class ScriptString { public: - ScriptString() {} - ScriptString(const String& s) : m_str(s) {} - ScriptString(const char* s) : m_str(s) {} + ScriptString() : m_impl(0) {} + ScriptString(const String& s) : m_impl(ScriptStringImpl::create(s)) {} + ScriptString(const char* s) : m_impl(ScriptStringImpl::create(s)) {} - operator String() const { return m_str; } + operator String() const { return m_impl->toString(); } - bool isNull() const { return m_str.isNull(); } - size_t size() const { return m_str.length(); } + bool isNull() const { return !m_impl.get() || m_impl->isNull(); } + size_t size() const { return m_impl->size(); } ScriptString& operator=(const char* s) { - m_str = s; + m_impl = ScriptStringImpl::create(s); return *this; } ScriptString& operator+=(const String& s) { - m_str += s; + m_impl->append(s); return *this; } + v8::Handle<v8::Value> v8StringOrNull() const + { + return isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(m_impl->v8StringHandle()); + } + private: - String m_str; + RefPtr<ScriptStringImpl> m_impl; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptStringImpl.cpp b/WebCore/bindings/v8/ScriptStringImpl.cpp new file mode 100644 index 0000000..afe74b1 --- /dev/null +++ b/WebCore/bindings/v8/ScriptStringImpl.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScriptStringImpl.h" + +#include "V8Binding.h" + +namespace WebCore { + +ScriptStringImpl::ScriptStringImpl(const String& s) +{ + v8::HandleScope scope; + m_handle.set(v8String(s)); +} + +ScriptStringImpl::ScriptStringImpl(const char* s) +{ + v8::HandleScope scope; + m_handle.set(v8::String::New(s)); +} + +String ScriptStringImpl::toString() const +{ + return v8StringToWebCoreString(m_handle.get()); +} + +bool ScriptStringImpl::isNull() const +{ + return m_handle.get().IsEmpty(); +} + +size_t ScriptStringImpl::size() const +{ + return m_handle.get()->Length(); +} + +void ScriptStringImpl::append(const String& s) +{ + v8::HandleScope scope; + if (m_handle.get().IsEmpty()) + m_handle.set(v8String(s)); + else + m_handle.set(v8::String::Concat(m_handle.get(), v8String(s))); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptStringImpl.h b/WebCore/bindings/v8/ScriptStringImpl.h new file mode 100644 index 0000000..8a47b4f --- /dev/null +++ b/WebCore/bindings/v8/ScriptStringImpl.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScriptStringImpl_h +#define ScriptStringImpl_h + +#include "OwnHandle.h" +#include "PlatformString.h" + +#include <v8.h> + +namespace WebCore { + +// This class is used for strings that tend to be shared with JavaScript frequently. The JSC implementation uses wtf::UString - see bindings/js/ScriptString.h +// Currently XMLHttpRequest uses a ScriptString to build up the responseText attribute. As data arrives from the network, it is appended to the ScriptString +// via operator+= and a JavaScript readystatechange event is fired. JavaScript can access the responseText attribute of the XMLHttpRequest object. JavaScript +// may also query the responseXML attribute of the XMLHttpRequest object which results in the responseText attribute being coerced into a WebCore::String and +// then parsed as an XML document. +// This implementation optimizes for the common case where the responseText is built up with many calls to operator+= before the actual text is queried. +class ScriptStringImpl : public RefCounted<ScriptStringImpl> { +public: + static PassRefPtr<ScriptStringImpl> create(const String& s) + { + return adoptRef(new ScriptStringImpl(s)); + } + + static PassRefPtr<ScriptStringImpl> create(const char* s) + { + return adoptRef(new ScriptStringImpl(s)); + } + + String toString() const; + + bool isNull() const; + size_t size() const; + + void append(const String& s); + + v8::Handle<v8::String> v8StringHandle() { return m_handle.get(); } + +private: + ScriptStringImpl(const String& s); + ScriptStringImpl(const char* s); + + OwnHandle<v8::String> m_handle; +}; + +} // namespace WebCore + +#endif // ScriptStringImpl_h diff --git a/WebCore/bindings/v8/ScriptValue.h b/WebCore/bindings/v8/ScriptValue.h index 004851b..c0ba8d5 100644 --- a/WebCore/bindings/v8/ScriptValue.h +++ b/WebCore/bindings/v8/ScriptValue.h @@ -44,6 +44,11 @@ namespace WebCore { class ScriptValue { public: + static ScriptValue quarantineValue(ScriptState* scriptState, const ScriptValue& value) + { + return value; + } + ScriptValue() {} ScriptValue(v8::Handle<v8::Value> value) @@ -110,7 +115,12 @@ public: { return m_value->IsUndefined(); } - + + bool isObject() const + { + return m_value->IsObject(); + } + bool hasNoValue() const { return m_value.IsEmpty(); @@ -128,12 +138,13 @@ public: m_value.Clear(); } - ~ScriptValue() + virtual ~ScriptValue() { clear(); } v8::Handle<v8::Value> v8Value() const { return m_value; } + bool getString(ScriptState*, String& result) const { return getString(result); } bool getString(String& result) const; String toString(ScriptState*) const; diff --git a/WebCore/bindings/v8/SerializedScriptValue.h b/WebCore/bindings/v8/SerializedScriptValue.h new file mode 100644 index 0000000..26a4199 --- /dev/null +++ b/WebCore/bindings/v8/SerializedScriptValue.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SerializedScriptValue_h +#define SerializedScriptValue_h + +#include "ScriptValue.h" +#include "V8Binding.h" +#include <v8.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +class SerializedScriptValue : public RefCounted<SerializedScriptValue> { +public: + static PassRefPtr<SerializedScriptValue> create(String string) + { + return adoptRef(new SerializedScriptValue(string)); + } + + static PassRefPtr<SerializedScriptValue> create() + { + return adoptRef(new SerializedScriptValue()); + } + + PassRefPtr<SerializedScriptValue> release() + { + RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data)); + m_data = String(); + return result.release(); + } + + String toString() + { + return m_data; + } + +private: + SerializedScriptValue(String string) + : m_data(string) + { + } + + SerializedScriptValue() { } + String m_data; +}; + +} // namespace WebCore + +#endif // SerializedScriptValue_h diff --git a/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp b/WebCore/bindings/v8/SharedPersistent.h index 5fe2710..8825bd5 100644 --- a/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp +++ b/WebCore/bindings/v8/SharedPersistent.h @@ -28,38 +28,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "CanvasPixelArray.h" +#ifndef SharedPersistent_h +#define SharedPersistent_h -#include "V8Binding.h" -#include "V8CustomBinding.h" -#include "V8Proxy.h" +#include <v8.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> namespace WebCore { -// Get the specified value from the pixel buffer and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid pixel buffer range return "undefined". -INDEXED_PROPERTY_GETTER(CanvasPixelArray) -{ - INC_STATS("DOM.CanvasPixelArray.IndexedPropertyGetter"); - CanvasPixelArray* pixelBuffer = V8DOMWrapper::convertToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); - - if ((index < 0) || (index >= pixelBuffer->length())) - return v8::Undefined(); - unsigned char result; - if (!pixelBuffer->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - -// Set the specified value in the pixel buffer. Accesses outside the valid pixel buffer range are silently ignored. -INDEXED_PROPERTY_SETTER(CanvasPixelArray) -{ - INC_STATS("DOM.CanvasPixelArray.IndexedPropertySetter"); - CanvasPixelArray* pixelBuffer = V8DOMWrapper::convertToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); - - if ((index >= 0) && (index < pixelBuffer->length())) - pixelBuffer->set(index, value->NumberValue()); - return value; -} + // A shareable reference to a v8 persistent handle. Using a shared + // persistent any number of objects can share a reference to a v8 + // object and when it should no longer be accessible the object's + // owner can clear it. + template <typename T> + class SharedPersistent : public RefCounted<SharedPersistent<T> > { + public: + void set(v8::Persistent<T> value) + { + m_value = value; + } + v8::Persistent<T> get() + { + return m_value; + } + void disposeHandle() + { + if (!m_value.IsEmpty()) { + m_value.Dispose(); + m_value.Clear(); + } + } + static PassRefPtr<SharedPersistent<T> > create(v8::Persistent<T> value) + { + return adoptRef(new SharedPersistent<T>(value)); + } + static PassRefPtr<SharedPersistent<T> > create() + { + return create(v8::Persistent<T>()); + } + private: + explicit SharedPersistent(v8::Persistent<T> value) : m_value(value) { } + v8::Persistent<T> m_value; + }; } // namespace WebCore + +#endif // SharedPersistent_h diff --git a/WebCore/bindings/v8/V8AbstractEventListener.cpp b/WebCore/bindings/v8/V8AbstractEventListener.cpp index 0c81846..0f5b5c8 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.cpp +++ b/WebCore/bindings/v8/V8AbstractEventListener.cpp @@ -31,42 +31,103 @@ #include "config.h" #include "V8AbstractEventListener.h" +#include "DateExtension.h" #include "Document.h" #include "Event.h" #include "Frame.h" -#include "Tokenizer.h" #include "V8Binding.h" +#include "V8EventListenerList.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" namespace WebCore { -V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute) - : m_isAttribute(isAttribute) - , m_frame(frame) - , m_lineNumber(0) - , m_columnNumber(0) +static void weakEventListenerCallback(v8::Persistent<v8::Value>, void* parameter) { - if (!m_frame) - return; + V8AbstractEventListener* listener = static_cast<V8AbstractEventListener*>(parameter); + listener->disposeListenerObject(); +} + +V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, const WorldContextHandle& worldContext) + : EventListener(JSEventListenerType) + , m_isWeak(true) + , m_isAttribute(isAttribute) + , m_worldContext(worldContext) +{ +} + +V8AbstractEventListener::~V8AbstractEventListener() +{ + if (!m_listener.IsEmpty()) { + v8::HandleScope scope; + v8::Local<v8::Object> listener = v8::Local<v8::Object>::New(m_listener); + V8EventListenerList::clearWrapper(listener, m_isAttribute); + } + disposeListenerObject(); +} + +void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event* event) +{ + // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. + // See issue 889829. + RefPtr<V8AbstractEventListener> protect(this); - // We might be called directly from the parser. v8::HandleScope handleScope; - m_context.set(V8Proxy::context(m_frame)); - m_context.makeWeak(); + v8::Local<v8::Context> v8Context = toV8Context(context, worldContext()); + if (v8Context.IsEmpty()) + return; + + // Enter the V8 context in which to perform the event handling. + v8::Context::Scope scope(v8Context); + + // Get the V8 wrapper for the event object. + v8::Handle<v8::Value> jsEvent = V8DOMWrapper::convertEventToV8Object(event); + + invokeEventHandler(context, event, jsEvent); + + Document::updateStyleForAllDocuments(); +} - // Get the position in the source if any. - if (m_isAttribute && m_frame->document()->tokenizer()) { - m_lineNumber = m_frame->document()->tokenizer()->lineNumber(); - m_columnNumber = m_frame->document()->tokenizer()->columnNumber(); +void V8AbstractEventListener::disposeListenerObject() +{ + if (!m_listener.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_listener); +#endif + m_listener.Dispose(); + m_listener.Clear(); } } -void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> v8Context, Event* event, v8::Handle<v8::Value> jsEvent, bool isWindowEvent) +void V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener) +{ + disposeListenerObject(); + m_listener = v8::Persistent<v8::Object>::New(listener); +#ifndef NDEBUG + V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener); +#endif + if (m_isWeak) + m_listener.MakeWeak(this, &weakEventListenerCallback); +} + +void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context, Event* event, v8::Handle<v8::Value> jsEvent) { + + v8::Local<v8::Context> v8Context = toV8Context(context, worldContext()); + if (v8Context.IsEmpty()) + return; + // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings. v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event"); v8::Local<v8::Value> returnValue; + // In beforeunload/unload handlers, we want to avoid sleeps which do tight loops of calling Date.getTime(). + if (event->type() == "beforeunload" || event->type() == "unload") + DateExtension::get()->setAllowSleep(false); + { // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire. v8::TryCatch tryCatch; @@ -81,8 +142,15 @@ void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> v8Conte tryCatch.Reset(); // Call the event handler. - returnValue = callListenerFunction(jsEvent, event, isWindowEvent); - tryCatch.Reset(); + returnValue = callListenerFunction(context, jsEvent, event); + if (!tryCatch.CanContinue()) + return; + + // If an error occurs while handling the event, it should be reported. + if (tryCatch.HasCaught()) { + reportException(0, tryCatch); + tryCatch.Reset(); + } // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) @@ -92,6 +160,9 @@ void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> v8Conte tryCatch.Reset(); } + if (event->type() == "beforeunload" || event->type() == "unload") + DateExtension::get()->setAllowSleep(true); + ASSERT(!V8Proxy::handleOutOfMemory() || returnValue.IsEmpty()); if (returnValue.IsEmpty()) @@ -106,56 +177,11 @@ void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> v8Conte event->preventDefault(); } -void V8AbstractEventListener::handleEvent(Event* event, bool isWindowEvent) -{ - // EventListener could be disconnected from the frame. - if (disconnected()) - return; - - // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. - // See issue 889829. - RefPtr<V8AbstractEventListener> protect(this); - - LOCK_V8; - v8::HandleScope handleScope; - - v8::Handle<v8::Context> v8Context = m_context.get(); - if (v8Context.IsEmpty()) - return; - - // m_frame can removed by the callback function, protect it until the callback function returns. - RefPtr<Frame> protectFrame(m_frame); - - // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(v8Context); - - // Get the V8 wrapper for the event object. - v8::Handle<v8::Value> jsEvent = V8DOMWrapper::convertEventToV8Object(event); - - invokeEventHandler(v8Context, event, jsEvent, isWindowEvent); - - Document::updateStyleForAllDocuments(); -} - -void V8AbstractEventListener::disposeListenerObject() -{ - if (!m_listener.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_listener); -#endif - m_listener.Dispose(); - m_listener.Clear(); - } -} - -v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event, bool isWindowEvent) +v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event) { if (!m_listener.IsEmpty() && !m_listener->IsFunction()) return v8::Local<v8::Object>::New(m_listener); - if (isWindowEvent) - return v8::Context::GetCurrent()->Global(); - EventTarget* target = event->currentTarget(); v8::Handle<v8::Value> value = V8DOMWrapper::convertEventTargetToV8Object(target); if (value.IsEmpty()) diff --git a/WebCore/bindings/v8/V8AbstractEventListener.h b/WebCore/bindings/v8/V8AbstractEventListener.h index 1521941..0afbed5 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.h +++ b/WebCore/bindings/v8/V8AbstractEventListener.h @@ -32,13 +32,17 @@ #define V8AbstractEventListener_h #include "EventListener.h" -#include "OwnHandle.h" +#include "WorldContextHandle.h" + #include <v8.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> namespace WebCore { class Event; class Frame; + class V8Proxy; // There are two kinds of event listeners: HTML or non-HMTL. onload, // onfocus, etc (attributes) are always HTML event handler type; Event @@ -50,54 +54,77 @@ namespace WebCore { // but ALLOWs duplicated non-HTML event handlers. class V8AbstractEventListener : public EventListener { public: - virtual ~V8AbstractEventListener() { } + virtual ~V8AbstractEventListener(); + + static const V8AbstractEventListener* cast(const EventListener* listener) + { + return listener->type() == JSEventListenerType + ? static_cast<const V8AbstractEventListener*>(listener) + : 0; + } + + static V8AbstractEventListener* cast(EventListener* listener) + { + return const_cast<V8AbstractEventListener*>(cast(const_cast<const EventListener*>(listener))); + } - // Returns the owner frame of the listener. - Frame* frame() { return m_frame; } + // Implementation of EventListener interface. - virtual void handleEvent(Event*, bool isWindowEvent); - void invokeEventHandler(v8::Handle<v8::Context>, Event*, v8::Handle<v8::Value> jsEvent, bool isWindowEvent); + virtual bool operator==(const EventListener& other) { return this == &other; } + + virtual void handleEvent(ScriptExecutionContext*, Event*); + + virtual bool isLazy() const { return false; } // Returns the listener object, either a function or an object. - virtual v8::Local<v8::Object> getListenerObject() + v8::Local<v8::Object> getListenerObject(ScriptExecutionContext* context) { + prepareListenerObject(context); return v8::Local<v8::Object>::New(m_listener); } + v8::Local<v8::Object> getExistingListenerObject() + { + return v8::Local<v8::Object>::New(m_listener); + } + + bool hasExistingListenerObject() + { + return !m_listener.IsEmpty(); + } + // Dispose listener object and clear the handle. void disposeListenerObject(); - virtual bool disconnected() const { return !m_frame; } + protected: + V8AbstractEventListener(bool isAttribute, const WorldContextHandle& worldContext); - virtual bool isObjectListener() const { return false; } + virtual void prepareListenerObject(ScriptExecutionContext*) { } - protected: - v8::Persistent<v8::Object> m_listener; + void setListenerObject(v8::Handle<v8::Object> listener); - // Indicates if this is an HTML type listener. - bool m_isAttribute; + void invokeEventHandler(ScriptExecutionContext*, Event*, v8::Handle<v8::Value> jsEvent); + + // Get the receiver object to use for event listener call. + v8::Local<v8::Object> getReceiverObject(Event*); + + const WorldContextHandle& worldContext() const { return m_worldContext; } private: - V8AbstractEventListener(Frame*, bool isInline); + // Implementation of EventListener function. + virtual bool virtualisAttribute() const { return m_isAttribute; } - virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsevent, Event*, bool isWindowEvent) = 0; + virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsevent, Event*) = 0; - // Get the receiver object to use for event listener call. - v8::Local<v8::Object> getReceiverObject(Event*, bool isWindowEvent); + v8::Persistent<v8::Object> m_listener; - // Frame to which the event listener is attached to. An event listener must be destroyed before its owner frame is - // deleted. See fast/dom/replaceChild.html - // FIXME: this could hold m_frame live until the event listener is deleted. - Frame* m_frame; - OwnHandle<v8::Context> m_context; + // Indicates if the above handle is weak. + bool m_isWeak; - // Position in the HTML source for HTML event listeners. - int m_lineNumber; - int m_columnNumber; + // Indicates if this is an HTML type listener. + bool m_isAttribute; - friend class V8EventListener; - friend class V8ObjectEventListener; - friend class V8LazyEventListener; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp index 0da910b..00286e5 100644 --- a/WebCore/bindings/v8/V8Binding.cpp +++ b/WebCore/bindings/v8/V8Binding.cpp @@ -33,8 +33,10 @@ #include "AtomicString.h" #include "CString.h" +#include "Element.h" #include "MathExtras.h" #include "PlatformString.h" +#include "QualifiedName.h" #include "StdLibExtras.h" #include "StringBuffer.h" #include "StringHash.h" @@ -55,7 +57,8 @@ public: #ifndef NDEBUG m_threadId = WTF::currentThread(); #endif - v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + ASSERT(!string.isNull()); + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * string.length()); } explicit WebCoreStringResource(const AtomicString& string) @@ -65,7 +68,8 @@ public: #ifndef NDEBUG m_threadId = WTF::currentThread(); #endif - v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + ASSERT(!string.isNull()); + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * string.length()); } virtual ~WebCoreStringResource() @@ -73,18 +77,18 @@ public: #ifndef NDEBUG ASSERT(m_threadId == WTF::currentThread()); #endif - int reducedExternalMemory = -2 * length(); - if (!m_plainString.impl()->inTable()) + int reducedExternalMemory = -2 * m_plainString.length(); + if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isNull()) reducedExternalMemory *= 2; v8::V8::AdjustAmountOfExternalAllocatedMemory(reducedExternalMemory); } - const uint16_t* data() const + virtual const uint16_t* data() const { - return reinterpret_cast<const uint16_t*>(m_plainString.characters()); + return reinterpret_cast<const uint16_t*>(m_plainString.impl()->characters()); } - size_t length() const { return m_plainString.length(); } + virtual size_t length() const { return m_plainString.impl()->length(); } String webcoreString() { return m_plainString; } @@ -95,8 +99,9 @@ public: #endif if (m_atomicString.isNull()) { m_atomicString = AtomicString(m_plainString); - if (!m_plainString.impl()->inTable()) - v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + ASSERT(!m_atomicString.isNull()); + if (m_plainString.impl() != m_atomicString.impl()) + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * m_atomicString.length()); } return m_atomicString; } @@ -121,12 +126,177 @@ private: #endif }; -String v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external, - StringType type) + +void* v8DOMWrapperToNative(v8::Handle<v8::Object> object) { + return object->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex); +} + +void* v8DOMWrapperToNative(const v8::AccessorInfo& info) { + return info.Holder()->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex); +} + + +String v8ValueToWebCoreString(v8::Handle<v8::Value> value) +{ + if (value->IsString()) + return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(value)); + return v8NonStringValueToWebCoreString(value); +} + +AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value) +{ + if (value->IsString()) + return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(value)); + return v8NonStringValueToAtomicWebCoreString(value); +} + +int toInt32(v8::Handle<v8::Value> value, bool& ok) +{ + ok = true; + + // Fast case. The value is already a 32-bit integer. + if (value->IsInt32()) + return value->Int32Value(); + + // Can the value be converted to a number? + v8::Local<v8::Number> numberObject = value->ToNumber(); + if (numberObject.IsEmpty()) { + ok = false; + return 0; + } + + // Does the value convert to nan or to an infinity? + double numberValue = numberObject->Value(); + if (isnan(numberValue) || isinf(numberValue)) { + ok = false; + return 0; + } + + // Can the value be converted to a 32-bit integer? + v8::Local<v8::Int32> intValue = value->ToInt32(); + if (intValue.IsEmpty()) { + ok = false; + return 0; + } + + // Return the result of the int32 conversion. + return intValue->Value(); +} + +String toWebCoreString(const v8::Arguments& args, int index) { + return v8ValueToWebCoreString(args[index]); +} + + +String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) +{ + if (value->IsNull()) + return String(); + return v8ValueToWebCoreString(value); +} + +AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) +{ + if (value->IsNull()) + return AtomicString(); + return v8ValueToAtomicWebCoreString(value); +} + +String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value) +{ + if (value->IsNull() || value->IsUndefined()) + return String(); + return toWebCoreString(value); +} + +bool isUndefinedOrNull(v8::Handle<v8::Value> value) +{ + return value->IsNull() || value->IsUndefined(); +} + +v8::Handle<v8::Boolean> v8Boolean(bool value) +{ + return value ? v8::True() : v8::False(); +} + +v8::Handle<v8::String> v8UndetectableString(const String& str) +{ + return v8::String::NewUndetectable(fromWebCoreString(str), str.length()); +} + +v8::Handle<v8::Value> v8StringOrNull(const String& str) +{ + return str.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(str)); +} + +v8::Handle<v8::Value> v8StringOrUndefined(const String& str) +{ + return str.isNull() ? v8::Handle<v8::Value>(v8::Undefined()) : v8::Handle<v8::Value>(v8String(str)); +} + +v8::Handle<v8::Value> v8StringOrFalse(const String& str) +{ + return str.isNull() ? v8::Handle<v8::Value>(v8::False()) : v8::Handle<v8::Value>(v8String(str)); +} + + +template <class S> struct StringTraits +{ + static S fromStringResource(WebCoreStringResource* resource); + + static S fromV8String(v8::Handle<v8::String> v8String, int length); +}; + +template<> +struct StringTraits<String> +{ + static String fromStringResource(WebCoreStringResource* resource) + { + return resource->webcoreString(); + } + + static String fromV8String(v8::Handle<v8::String> v8String, int length) + { + ASSERT(v8String->Length() == length); + // NOTE: as of now, String(const UChar*, int) performs String::createUninitialized + // anyway, so no need to optimize like we do for AtomicString below. + UChar* buffer; + String result = String::createUninitialized(length, buffer); + v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); + return result; + } +}; + +template<> +struct StringTraits<AtomicString> +{ + static AtomicString fromStringResource(WebCoreStringResource* resource) + { + return resource->atomicString(); + } + + static AtomicString fromV8String(v8::Handle<v8::String> v8String, int length) + { + ASSERT(v8String->Length() == length); + static const int inlineBufferSize = 16; + if (length <= inlineBufferSize) { + UChar inlineBuffer[inlineBufferSize]; + v8String->Write(reinterpret_cast<uint16_t*>(inlineBuffer), 0, length); + return AtomicString(inlineBuffer, length); + } + UChar* buffer; + String tmp = String::createUninitialized(length, buffer); + v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); + return AtomicString(tmp); + } +}; + +template <typename StringType> +StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external) { WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String); if (stringResource) - return stringResource->webcoreString(); + return StringTraits<StringType>::fromStringResource(stringResource); int length = v8String->Length(); if (!length) { @@ -134,44 +304,27 @@ String v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode ext return StringImpl::empty(); } - UChar* buffer; - String result = String::createUninitialized(length, buffer); - v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); + StringType result(StringTraits<StringType>::fromV8String(v8String, length)); - if (type == AtomicStringType) - result = AtomicString(result); - - if (external == Externalize) { - WebCoreStringResource* resource = new WebCoreStringResource(result); - if (!v8String->MakeExternal(resource)) { + if (external == Externalize && v8String->CanMakeExternal()) { + stringResource = new WebCoreStringResource(result); + if (!v8String->MakeExternal(stringResource)) { // In case of a failure delete the external resource as it was not used. - delete resource; + delete stringResource; } } return result; } + +// Explicitly instantiate the above template with the expected parameterizations, +// to ensure the compiler generates the code; otherwise link errors can result in GCC 4.4. +template String v8StringToWebCoreString<String>(v8::Handle<v8::String>, ExternalMode); +template AtomicString v8StringToWebCoreString<AtomicString>(v8::Handle<v8::String>, ExternalMode); -AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String) -{ - WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String); - if (!stringResource) { - // If this string hasn't been externalized, we force it now. - String plain = v8StringToWebCoreString(v8String, Externalize, AtomicStringType); - // If the string is empty there's no room to cache an atomic - // string so we bail out. - if (plain.isEmpty()) - return plain; - stringResource = WebCoreStringResource::toStringResource(v8String); - ASSERT(stringResource != NULL); - } - return stringResource->atomicString(); -} -String v8ValueToWebCoreString(v8::Handle<v8::Value> object) +String v8NonStringValueToWebCoreString(v8::Handle<v8::Value> object) { - if (object->IsString()) - return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(object), Externalize, PlainStringType); - + ASSERT(!object->IsString()); if (object->IsInt32()) { int value = object->Int32Value(); // Most numbers used are <= 100. Even if they aren't used there's very little in using the space. @@ -197,20 +350,13 @@ String v8ValueToWebCoreString(v8::Handle<v8::Value> object) throwError(block.Exception()); return StringImpl::empty(); } - return v8StringToWebCoreString(v8String, DoNotExternalize, PlainStringType); + return v8StringToWebCoreString<String>(v8String, DoNotExternalize); } -AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> v8Value) +AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value> object) { - if (v8Value->IsString()) - return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(v8Value)); - String string = v8ValueToWebCoreString(v8Value); - return AtomicString(string); -} - -v8::Handle<v8::String> v8String(const String& string) -{ - return v8ExternalString(string); + ASSERT(!object->IsString()); + return AtomicString(v8NonStringValueToWebCoreString(object)); } static bool stringImplCacheEnabled = false; @@ -251,17 +397,17 @@ static void cachedStringCallback(v8::Persistent<v8::Value> wrapper, void* parame v8::Local<v8::String> v8ExternalString(const String& string) { - if (!string.length()) + StringImpl* stringImpl = string.impl(); + if (!stringImpl || !stringImpl->length()) return v8::String::Empty(); if (!stringImplCacheEnabled) return makeExternalString(string); - StringImpl* stringImpl = string.impl(); StringCache& stringCache = getStringCache(); v8::String* cachedV8String = stringCache.get(stringImpl); if (cachedV8String) - return v8::Local<v8::String>(cachedV8String); + return v8::Local<v8::String>::New(v8::Handle<v8::String>(cachedV8String)); v8::Local<v8::String> newString = makeExternalString(string); if (newString.IsEmpty()) @@ -277,5 +423,65 @@ v8::Local<v8::String> v8ExternalString(const String& string) return newString; } + +v8::Persistent<v8::FunctionTemplate> createRawTemplate() +{ + v8::HandleScope scope; + v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8Proxy::checkNewLegal); + return v8::Persistent<v8::FunctionTemplate>::New(result); +} + +v8::Local<v8::Signature> configureTemplate(v8::Persistent<v8::FunctionTemplate>desc, + const char *interfaceName, + V8ClassIndex::V8WrapperType parentClassIndex, + int fieldCount, + const BatchedAttribute* attributes, + size_t attributeCount, + const BatchedCallback* callbacks, + size_t callbackCount) +{ + desc->SetClassName(v8::String::New(interfaceName)); + v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); + instance->SetInternalFieldCount(fieldCount); + if (parentClassIndex) + desc->Inherit(V8DOMWrapper::getTemplate(parentClassIndex)); + if (attributeCount) + batchConfigureAttributes(instance, desc->PrototypeTemplate(), + attributes, attributeCount); + v8::Local<v8::Signature> defaultSignature = v8::Signature::New(desc); + if (callbackCount) + batchConfigureCallbacks(desc->PrototypeTemplate(), + defaultSignature, + static_cast<v8::PropertyAttribute>(v8::DontDelete), + callbacks, callbackCount); + return defaultSignature; +} + +void createCallback(v8::Local<v8::ObjectTemplate> proto, + const char *name, + v8::InvocationCallback callback, + v8::Handle<v8::Signature> signature, + v8::PropertyAttribute attribute) +{ + proto->Set(v8::String::New(name), + v8::FunctionTemplate::New(callback, v8::Handle<v8::Value>(), signature), + attribute); +} + +v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo& info, + const QualifiedName& name) +{ + Element *imp = v8DOMWrapperToNode<Element>(info); + return v8ExternalString(imp->getAttribute(name)); +} + +void setElementStringAttr(const v8::AccessorInfo& info, + const QualifiedName& name, + v8::Local<v8::Value> value) +{ + Element* imp = v8DOMWrapperToNode<Element>(info); + AtomicString v = toAtomicWebCoreStringWithNullCheck(value); + imp->setAttribute(name, v); +} } // namespace WebCore diff --git a/WebCore/bindings/v8/V8Binding.h b/WebCore/bindings/v8/V8Binding.h index 4f36f00..de5bb4c 100644 --- a/WebCore/bindings/v8/V8Binding.h +++ b/WebCore/bindings/v8/V8Binding.h @@ -31,46 +31,122 @@ #ifndef V8Binding_h #define V8Binding_h +#include "AtomicString.h" #include "MathExtras.h" #include "PlatformString.h" +#include "V8DOMWrapper.h" +#include "V8Index.h" #include <v8.h> namespace WebCore { + + class EventListener; + class EventTarget; + + // A helper function extract native object pointer from a DOM wrapper + // and cast to the specified type. + void* v8DOMWrapperToNative(v8::Handle<v8::Object>); + + template <class C> + C* v8DOMWrapperTo(v8::Handle<v8::Object> object) + { + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + return reinterpret_cast<C*>(v8DOMWrapperToNative(object)); + } + template <class C> + C* v8DOMWrapperToNode(v8::Handle<v8::Object> object) + { + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + ASSERT(V8DOMWrapper::domWrapperType(object) == V8ClassIndex::NODE); + return reinterpret_cast<C*>(v8DOMWrapperToNative(object)); + } + + void* v8DOMWrapperToNative(const v8::AccessorInfo&); + + template <class C> + C* v8DOMWrapperTo(const v8::AccessorInfo& info) { + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + return reinterpret_cast<C*>(v8DOMWrapperToNative(info)); + } + template <class C> + C* v8DOMWrapperToNode(const v8::AccessorInfo& info) { + ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); + return reinterpret_cast<C*>(v8DOMWrapperToNative(info)); + } + + template <class C> + C* v8DOMWrapperTo(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) + { + // Native event listener is per frame, it cannot be handled by this generic function. + ASSERT(type != V8ClassIndex::EVENTLISTENER); + ASSERT(type != V8ClassIndex::EVENTTARGET); + + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + +#ifndef NDEBUG + const bool typeIsValid = +#define MAKE_CASE(TYPE, NAME) (type != V8ClassIndex::TYPE) && + DOM_NODE_TYPES(MAKE_CASE) +#if ENABLE(SVG) + SVG_NODE_TYPES(MAKE_CASE) +#endif +#undef MAKE_CASE + true; + ASSERT(typeIsValid); +#endif + + return v8DOMWrapperTo<C>(object); + } + + template <class C> + C* v8DOMWrapperTo(V8ClassIndex::V8WrapperType type, const v8::AccessorInfo& info) + { +#ifndef NDEBUG + return v8DOMWrapperTo<C>(type, info.Holder()); +#else + return reinterpret_cast<C*>(v8DOMWrapperToNative(info)); +#endif + } + enum ExternalMode { Externalize, DoNotExternalize }; - - enum StringType { - PlainStringType, - AtomicStringType - }; + + template <typename StringType> + StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external); // Convert v8 types to a WebCore::String. If the V8 string is not already // an external string then it is transformed into an external string at this // point to avoid repeated conversions. - String v8StringToWebCoreString(v8::Handle<v8::String>, ExternalMode mode, StringType type); - String v8ValueToWebCoreString(v8::Handle<v8::Value>); + inline String v8StringToWebCoreString(v8::Handle<v8::String> v8String) + { + return v8StringToWebCoreString<String>(v8String, Externalize); + } + String v8NonStringValueToWebCoreString(v8::Handle<v8::Value>); + String v8ValueToWebCoreString(v8::Handle<v8::Value> value); // Convert v8 types to a WebCore::AtomicString. - AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String>); - AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value>); - - // Convert a string to a V8 string. - v8::Handle<v8::String> v8String(const String&); - - inline String toString(const String& string)
- {
- return string;
+ inline AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String) + { + return v8StringToWebCoreString<AtomicString>(v8String, Externalize); } + AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value>); + AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value); // Return a V8 external string that shares the underlying buffer with the given // WebCore string. The reference counting mechanism is used to keep the // underlying buffer alive while the string is still live in the V8 engine. v8::Local<v8::String> v8ExternalString(const String&); + // Convert a string to a V8 string. + inline v8::Handle<v8::String> v8String(const String& string) + { + return v8ExternalString(string); + } + // Enables caching v8 wrappers created for WebCore::StringImpl. Currently this cache requires // all the calls (both to convert WebCore::String to v8::String and to GC the handle) // to be performed on the main thread. @@ -78,38 +154,7 @@ namespace WebCore { // Convert a value to a 32-bit integer. The conversion fails if the // value cannot be converted to an integer or converts to nan or to an infinity. - inline int toInt32(v8::Handle<v8::Value> value, bool& ok) - { - ok = true; - - // Fast case. The value is already a 32-bit integer. - if (value->IsInt32()) - return value->Int32Value(); - - // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); - if (numberObject.IsEmpty()) { - ok = false; - return 0; - } - - // Does the value convert to nan or to an infinity? - double numberValue = numberObject->Value(); - if (isnan(numberValue) || isinf(numberValue)) { - ok = false; - return 0; - } - - // Can the value be converted to a 32-bit integer? - v8::Local<v8::Int32> intValue = value->ToInt32(); - if (intValue.IsEmpty()) { - ok = false; - return 0; - } - - // Return the result of the int32 conversion. - return intValue->Value(); - } + int toInt32(v8::Handle<v8::Value> value, bool& ok); // Convert a value to a 32-bit integer assuming the conversion cannot fail. inline int toInt32(v8::Handle<v8::Value> value) @@ -128,6 +173,8 @@ namespace WebCore { { return v8ValueToWebCoreString(object); } + + String toWebCoreString(const v8::Arguments&, int index); // The string returned by this function is still owned by the argument // and will be deallocated when the argument is deallocated. @@ -136,49 +183,78 @@ namespace WebCore { return reinterpret_cast<const uint16_t*>(str.characters()); } - inline bool isUndefinedOrNull(v8::Handle<v8::Value> value) - { - return value->IsNull() || value->IsUndefined(); - } + bool isUndefinedOrNull(v8::Handle<v8::Value> value); - inline v8::Handle<v8::Boolean> v8Boolean(bool value) - { - return value ? v8::True() : v8::False(); - } - - inline String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) - { - if (value->IsNull()) - return String(); - return v8ValueToWebCoreString(value); - } + v8::Handle<v8::Boolean> v8Boolean(bool value); - inline String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value) - { - if (value->IsNull() || value->IsUndefined()) - return String(); - return toWebCoreString(value); - } + String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value); + + AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value); + + String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value); - inline v8::Handle<v8::String> v8UndetectableString(const String& str) - { - return v8::String::NewUndetectable(fromWebCoreString(str), str.length()); - } + v8::Handle<v8::String> v8UndetectableString(const String& str); - inline v8::Handle<v8::Value> v8StringOrNull(const String& str) - { - return str.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(str)); - } + v8::Handle<v8::Value> v8StringOrNull(const String& str); - inline v8::Handle<v8::Value> v8StringOrUndefined(const String& str) - { - return str.isNull() ? v8::Handle<v8::Value>(v8::Undefined()) : v8::Handle<v8::Value>(v8String(str)); - } + v8::Handle<v8::Value> v8StringOrUndefined(const String& str); + + v8::Handle<v8::Value> v8StringOrFalse(const String& str); + + v8::Persistent<v8::FunctionTemplate> createRawTemplate(); + + struct BatchedAttribute; + struct BatchedCallback; + + v8::Local<v8::Signature> configureTemplate(v8::Persistent<v8::FunctionTemplate>, + const char *interfaceName, + V8ClassIndex::V8WrapperType parentClassIndex, + int fieldCount, + const BatchedAttribute*, + size_t attributeCount, + const BatchedCallback*, + size_t callbackCount); + + void createCallback(v8::Local<v8::ObjectTemplate> proto, + const char *name, + v8::InvocationCallback, + v8::Handle<v8::Signature>, + v8::PropertyAttribute attributes = v8::DontDelete); + + v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo&, + const QualifiedName&); + void setElementStringAttr(const v8::AccessorInfo&, + const QualifiedName&, + v8::Local<v8::Value>); + + v8::Handle<v8::Value> getElementEventHandlerAttr(const v8::AccessorInfo&, + const AtomicString&); + + // V8Parameter is an adapter class that converts V8 values to Strings + // or AtomicStrings as appropriate, using multiple typecast operators. + enum V8ParameterMode { + DefaultMode, + WithNullCheck, + WithUndefinedOrNullCheck + }; + template <V8ParameterMode MODE = DefaultMode> + class V8Parameter { + public: + V8Parameter (v8::Local<v8::Value> object) :m_v8Object(object) { } + operator String(); + operator AtomicString(); + private: + v8::Local<v8::Value> m_v8Object; + }; + + template<> inline V8Parameter<DefaultMode>::operator String() { return toWebCoreString(m_v8Object); } + template<> inline V8Parameter<WithNullCheck>::operator String() { return toWebCoreStringWithNullCheck(m_v8Object); } + template<> inline V8Parameter<WithUndefinedOrNullCheck>::operator String() { return toWebCoreStringWithNullOrUndefinedCheck(m_v8Object); } + + template<> inline V8Parameter<DefaultMode>::operator AtomicString() { return v8ValueToAtomicWebCoreString(m_v8Object); } + template<> inline V8Parameter<WithNullCheck>::operator AtomicString() { return toAtomicWebCoreStringWithNullCheck(m_v8Object); } + template<> inline V8Parameter<WithUndefinedOrNullCheck>::operator AtomicString() { return toAtomicWebCoreStringWithNullCheck(m_v8Object); } - inline v8::Handle<v8::Value> v8StringOrFalse(const String& str) - { - return str.isNull() ? v8::Handle<v8::Value>(v8::False()) : v8::Handle<v8::Value>(v8String(str)); - } } // namespace WebCore #endif // V8Binding_h diff --git a/WebCore/bindings/v8/V8Collection.h b/WebCore/bindings/v8/V8Collection.h index cbfe921..0a4134e 100644 --- a/WebCore/bindings/v8/V8Collection.h +++ b/WebCore/bindings/v8/V8Collection.h @@ -41,7 +41,7 @@ namespace WebCore { // FIXME: These functions should be named using to* since they return the item (get* is used for method that take a ref param). // See https://bugs.webkit.org/show_bug.cgi?id=24664. - static v8::Handle<v8::Value> getV8Object(void* implementation, v8::Local<v8::Value> implementationType) + inline v8::Handle<v8::Value> getV8Object(void* implementation, v8::Local<v8::Value> implementationType) { if (!implementation) return v8::Handle<v8::Value>(); @@ -177,6 +177,18 @@ namespace WebCore { } + // A template for indexed getters on collections of strings. + template<class Collection> static v8::Handle<v8::Value> collectionStringIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) + { + // FIXME: assert that object must be a collection type + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); + String result = collection->item(index); + return v8String(result); + } + + // Add indexed getter to the function template for a collection. template<class Collection, class ItemType> static void setCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) { @@ -208,6 +220,13 @@ namespace WebCore { desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionStringOrNullIndexedPropertyGetter<Collection>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>); } + + // Add indexed getter returning a string to a function template for a collection. + template<class Collection> static void setCollectionStringIndexedGetter(v8::Handle<v8::FunctionTemplate> desc) + { + desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionStringIndexedPropertyGetter<Collection>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>); + } + v8::Handle<v8::Value> toOptionsCollectionSetter(uint32_t index, v8::Handle<v8::Value>, HTMLSelectElement*); } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMMap.cpp b/WebCore/bindings/v8/V8DOMMap.cpp index 1bd68f7..acd88ec 100644 --- a/WebCore/bindings/v8/V8DOMMap.cpp +++ b/WebCore/bindings/v8/V8DOMMap.cpp @@ -34,6 +34,7 @@ #include "DOMData.h" #include "DOMDataStore.h" #include "DOMObjectsInclude.h" +#include "MainThreadDOMData.h" #include "ScopedDOMDataStore.h" namespace WebCore { @@ -47,33 +48,49 @@ DOMDataStoreHandle::~DOMDataStoreHandle() { } +static bool fasterDOMStoreAccess = false; + +static inline DOMDataStore& getDOMDataStore() +{ + if (LIKELY(fasterDOMStoreAccess)) { + ASSERT(WTF::isMainThread()); + return MainThreadDOMData::getCurrentMainThreadStore(); + } + + return DOMData::getCurrent()->getStore(); +} + +void enableFasterDOMStoreAccess() +{ + fasterDOMStoreAccess = true; +} + DOMWrapperMap<Node>& getDOMNodeMap() { - // Nodes only exist on the main thread. - return DOMData::getCurrentMainThread()->getStore().domNodeMap(); + return getDOMDataStore().domNodeMap(); } DOMWrapperMap<void>& getDOMObjectMap() { - return DOMData::getCurrent()->getStore().domObjectMap(); + return getDOMDataStore().domObjectMap(); } DOMWrapperMap<void>& getActiveDOMObjectMap() { - return DOMData::getCurrent()->getStore().activeDomObjectMap(); + return getDOMDataStore().activeDomObjectMap(); } #if ENABLE(SVG) DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() { - return DOMData::getCurrent()->getStore().domSvgElementInstanceMap(); + return getDOMDataStore().domSvgElementInstanceMap(); } // Map of SVG objects with contexts to V8 objects DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() { - return DOMData::getCurrent()->getStore().domSvgObjectWithContextMap(); + return getDOMDataStore().domSvgObjectWithContextMap(); } #endif // ENABLE(SVG) diff --git a/WebCore/bindings/v8/V8DOMMap.h b/WebCore/bindings/v8/V8DOMMap.h index 754ac3a..b6861d4 100644 --- a/WebCore/bindings/v8/V8DOMMap.h +++ b/WebCore/bindings/v8/V8DOMMap.h @@ -140,6 +140,8 @@ namespace WebCore { DOMWrapperMap<void>& getDOMSVGObjectWithContextMap(); void visitDOMSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); #endif + + void enableFasterDOMStoreAccess(); } // namespace WebCore #endif // V8DOMMap_h diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp index 8a9741a..6a691a9 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -31,21 +31,33 @@ #include "config.h" #include "V8DOMWrapper.h" +#include "CSSMutableStyleDeclaration.h" +// ANDROID: Upstream CHROMIUM guard. #if PLATFORM(CHROMIUM) #include "ChromiumBridge.h" #endif -#include "CSSMutableStyleDeclaration.h" #include "DOMObjectsInclude.h" #include "DocumentLoader.h" #include "FrameLoaderClient.h" +#include "Notification.h" +// ANDROID: Upstream SVG guard. +#if ENABLE(SVG) +#include "SVGElementInstance.h" +#endif #include "ScriptController.h" +#include "V8AbstractEventListener.h" #include "V8Binding.h" #include "V8Collection.h" #include "V8CustomBinding.h" +#include "V8CustomEventListener.h" #include "V8DOMMap.h" #include "V8DOMWindow.h" +#include "V8EventListenerList.h" #include "V8Index.h" #include "V8IsolatedWorld.h" +#include "V8Proxy.h" +#include "WebGLArray.h" +#include "WebGLUniformLocation.h" #include "WorkerContextExecutionProxy.h" #include <algorithm> @@ -145,11 +157,64 @@ v8::Handle<v8::Value> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8Clas #endif +#if ENABLE(3D_CANVAS) +void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle<v8::Object> wrapper, + int index, + void* address, + int length) +{ + v8::ExternalArrayType array_type = v8::kExternalByteArray; + V8ClassIndex::V8WrapperType classIndex = V8ClassIndex::FromInt(index); + switch (classIndex) { + case V8ClassIndex::WEBGLBYTEARRAY: + array_type = v8::kExternalByteArray; + break; + case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: + array_type = v8::kExternalUnsignedByteArray; + break; + case V8ClassIndex::WEBGLSHORTARRAY: + array_type = v8::kExternalShortArray; + break; + case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: + array_type = v8::kExternalUnsignedShortArray; + break; + case V8ClassIndex::WEBGLINTARRAY: + array_type = v8::kExternalIntArray; + break; + case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: + array_type = v8::kExternalUnsignedIntArray; + break; + case V8ClassIndex::WEBGLFLOATARRAY: + array_type = v8::kExternalFloatArray; + break; + default: + ASSERT_NOT_REACHED(); + } + wrapper->SetIndexedPropertiesToExternalArrayData(address, + array_type, + length); +} +#endif + bool V8DOMWrapper::domObjectHasJSWrapper(void* object) { return getDOMObjectMap().contains(object) || getActiveDOMObjectMap().contains(object); } +v8::Persistent<v8::Object> V8DOMWrapper::jsWrapperForDOMObject(void* object) +{ + v8::Persistent<v8::Object> wrapper = getDOMObjectMap().get(object); + ASSERT(!wrapper.IsEmpty()); + return wrapper; +} + +v8::Persistent<v8::Object> V8DOMWrapper::jsWrapperForActiveDOMObject(void* object) +{ + v8::Persistent<v8::Object> wrapper = getActiveDOMObjectMap().get(object); + ASSERT(!wrapper.IsEmpty()); + return wrapper; +} + // The caller must have increased obj's ref count. void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper) { @@ -217,7 +282,7 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W // setter. Therefore, the interceptor has to be on the object // itself and not on the prototype object. descriptor->InstanceTemplate()->SetNamedPropertyHandler( USE_NAMED_PROPERTY_GETTER(CSSStyleDeclaration), USE_NAMED_PROPERTY_SETTER(CSSStyleDeclaration)); - setCollectionStringOrNullIndexedGetter<CSSStyleDeclaration>(descriptor); + setCollectionStringIndexedGetter<CSSStyleDeclaration>(descriptor); break; case V8ClassIndex::CSSRULELIST: setCollectionIndexedGetter<CSSRuleList, CSSRule>(descriptor, V8ClassIndex::CSSRULE); @@ -226,7 +291,7 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W setCollectionIndexedGetter<CSSValueList, CSSValue>(descriptor, V8ClassIndex::CSSVALUE); break; case V8ClassIndex::CSSVARIABLESDECLARATION: - setCollectionStringOrNullIndexedGetter<CSSVariablesDeclaration>(descriptor); + setCollectionStringIndexedGetter<CSSVariablesDeclaration>(descriptor); break; case V8ClassIndex::WEBKITCSSTRANSFORMVALUE: setCollectionIndexedGetter<WebKitCSSTransformValue, CSSValue>(descriptor, V8ClassIndex::CSSVALUE); @@ -308,10 +373,15 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W case V8ClassIndex::MIMETYPEARRAY: setCollectionIndexedAndNamedGetters<MimeTypeArray, MimeType>(descriptor, V8ClassIndex::MIMETYPE); break; - case V8ClassIndex::NAMEDNODEMAP: - descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NamedNodeMap)); - descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(NamedNodeMap), 0, 0, 0, collectionIndexedPropertyEnumerator<NamedNodeMap>, v8::Integer::New(V8ClassIndex::NODE)); + case V8ClassIndex::NAMEDNODEMAP: { + // We add an extra internal field to hold a reference to the owner node. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kNamedNodeMapInternalFieldCount); + instanceTemplate->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NamedNodeMap)); + instanceTemplate->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(NamedNodeMap), 0, 0, 0, collectionIndexedPropertyEnumerator<NamedNodeMap>, v8::Integer::New(V8ClassIndex::NODE)); break; + } #if ENABLE(DOM_STORAGE) case V8ClassIndex::STORAGE: descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(Storage), USE_NAMED_PROPERTY_SETTER(Storage), 0, USE_NAMED_PROPERTY_DELETER(Storage), V8Custom::v8StorageNamedPropertyEnumerator); @@ -337,6 +407,7 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W descriptor->PrototypeTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DOMWindow)); descriptor->PrototypeTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DOMWindow)); + descriptor->PrototypeTemplate()->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount); descriptor->SetHiddenPrototype(true); @@ -381,6 +452,24 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W break; } +#if ENABLE(NOTIFICATIONS) + case V8ClassIndex::NOTIFICATION: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kNotificationInternalFieldCount); + break; + } +#endif // NOTIFICATIONS + +#if ENABLE(SVG) + case V8ClassIndex::SVGELEMENTINSTANCE: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kSVGElementInstanceInternalFieldCount); + break; + } +#endif + #if ENABLE(WORKERS) case V8ClassIndex::ABSTRACTWORKER: { // Reserve one more internal field for keeping event listeners. @@ -415,6 +504,24 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W #endif // WORKERS +#if ENABLE(SHARED_WORKERS) + case V8ClassIndex::SHAREDWORKER: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kSharedWorkerInternalFieldCount); + descriptor->SetCallHandler(USE_CALLBACK(SharedWorkerConstructor)); + break; + } + + case V8ClassIndex::SHAREDWORKERCONTEXT: { + // Reserve internal fields for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kSharedWorkerContextInternalFieldCount); + break; + } +#endif // SHARED_WORKERS + #if ENABLE(OFFLINE_WEB_APPLICATIONS) case V8ClassIndex::DOMAPPLICATIONCACHE: { // Reserve one more internal field for keeping event listeners. @@ -424,20 +531,35 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W } #endif +#if ENABLE(3D_CANVAS) // The following objects are created from JavaScript. - case V8ClassIndex::DOMPARSER: - descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor)); + case V8ClassIndex::WEBGLARRAYBUFFER: + descriptor->SetCallHandler(USE_CALLBACK(WebGLArrayBufferConstructor)); break; -#if ENABLE(VIDEO) - case V8ClassIndex::HTMLAUDIOELEMENT: - descriptor->SetCallHandler(USE_CALLBACK(HTMLAudioElementConstructor)); + case V8ClassIndex::WEBGLBYTEARRAY: + descriptor->SetCallHandler(USE_CALLBACK(WebGLByteArrayConstructor)); break; -#endif - case V8ClassIndex::HTMLIMAGEELEMENT: - descriptor->SetCallHandler(USE_CALLBACK(HTMLImageElementConstructor)); + case V8ClassIndex::WEBGLFLOATARRAY: + descriptor->SetCallHandler(USE_CALLBACK(WebGLFloatArrayConstructor)); + break; + case V8ClassIndex::WEBGLINTARRAY: + descriptor->SetCallHandler(USE_CALLBACK(WebGLIntArrayConstructor)); break; - case V8ClassIndex::HTMLOPTIONELEMENT: - descriptor->SetCallHandler(USE_CALLBACK(HTMLOptionElementConstructor)); + case V8ClassIndex::WEBGLSHORTARRAY: + descriptor->SetCallHandler(USE_CALLBACK(WebGLShortArrayConstructor)); + break; + case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: + descriptor->SetCallHandler(USE_CALLBACK(WebGLUnsignedByteArrayConstructor)); + break; + case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: + descriptor->SetCallHandler(USE_CALLBACK(WebGLUnsignedIntArrayConstructor)); + break; + case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: + descriptor->SetCallHandler(USE_CALLBACK(WebGLUnsignedShortArrayConstructor)); + break; +#endif + case V8ClassIndex::DOMPARSER: + descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor)); break; case V8ClassIndex::WEBKITCSSMATRIX: descriptor->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor)); @@ -445,6 +567,15 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W case V8ClassIndex::WEBKITPOINT: descriptor->SetCallHandler(USE_CALLBACK(WebKitPointConstructor)); break; +#if ENABLE(WEB_SOCKETS) + case V8ClassIndex::WEBSOCKET: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kWebSocketInternalFieldCount); + descriptor->SetCallHandler(USE_CALLBACK(WebSocketConstructor)); + break; + } +#endif case V8ClassIndex::XMLSERIALIZER: descriptor->SetCallHandler(USE_CALLBACK(XMLSerializerConstructor)); break; @@ -461,18 +592,20 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount); break; } +// ANDROID: Upstream XPATH guard. #if ENABLE(XPATH) case V8ClassIndex::XPATHEVALUATOR: descriptor->SetCallHandler(USE_CALLBACK(XPathEvaluatorConstructor)); break; #endif +// ANDROID: Upstream XSLT guard. #if ENABLE(XSLT) case V8ClassIndex::XSLTPROCESSOR: descriptor->SetCallHandler(USE_CALLBACK(XSLTProcessorConstructor)); break; #endif +// ANDROID: Upstream TOUCH_EVENTS. #if ENABLE(TOUCH_EVENTS) - // TODO(andreip): upstream touch related changes to Chromium case V8ClassIndex::TOUCHLIST: { v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); instanceTemplate->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(TouchList)); @@ -482,6 +615,9 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W case V8ClassIndex::CLIENTRECTLIST: descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(ClientRectList)); break; + case V8ClassIndex::FILELIST: + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(FileList)); + break; #if ENABLE(DATAGRID) case V8ClassIndex::DATAGRIDCOLUMNLIST: descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DataGridColumnList)); @@ -562,6 +698,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperTyp // These objects can be constructed under WorkerContextExecutionProxy. They need special // handling, since if we proceed below V8Proxy::retrieve() will get called and will crash. + // TODO(ukai): websocket? if ((type == V8ClassIndex::DOMCOREEXCEPTION || type == V8ClassIndex::RANGEEXCEPTION || type == V8ClassIndex::EVENTEXCEPTION @@ -587,6 +724,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperTyp return convertStyleSheetToV8Object(static_cast<StyleSheet*>(impl)); case V8ClassIndex::DOMWINDOW: return convertWindowToV8Object(static_cast<DOMWindow*>(impl)); + case V8ClassIndex::NAMEDNODEMAP: + return convertNamedNodeMapToV8Object(static_cast<NamedNodeMap*>(impl)); #if ENABLE(SVG) SVG_NONNODE_TYPES(MAKE_CASE) if (type == V8ClassIndex::SVGELEMENTINSTANCE) @@ -609,6 +748,27 @@ v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperTyp // Non DOM node v8::Persistent<v8::Object> result = isActiveDomObject ? getActiveDOMObjectMap().get(impl) : getDOMObjectMap().get(impl); if (result.IsEmpty()) { +#if ENABLE(3D_CANVAS) + if (type == V8ClassIndex::WEBGLARRAY && impl) { + // Determine which subclass we are wrapping. + WebGLArray* array = reinterpret_cast<WebGLArray*>(impl); + if (array->isByteArray()) + type = V8ClassIndex::WEBGLBYTEARRAY; + else if (array->isFloatArray()) + type = V8ClassIndex::WEBGLFLOATARRAY; + else if (array->isIntArray()) + type = V8ClassIndex::WEBGLINTARRAY; + else if (array->isShortArray()) + type = V8ClassIndex::WEBGLSHORTARRAY; + else if (array->isUnsignedByteArray()) + type = V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY; + else if (array->isUnsignedIntArray()) + type = V8ClassIndex::WEBGLUNSIGNEDINTARRAY; + else if (array->isUnsignedShortArray()) + type = V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY; + } +#endif + v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, impl); if (!v8Object.IsEmpty()) { // Go through big switch statement, it has some duplications @@ -632,6 +792,28 @@ v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperTyp result->SetIndexedPropertiesToPixelData(pixels->data()->data(), pixels->length()); } +#if ENABLE(3D_CANVAS) + // Set up WebGLArray subclasses' accesses similarly. + switch (type) { + case V8ClassIndex::WEBGLBYTEARRAY: + case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: + case V8ClassIndex::WEBGLSHORTARRAY: + case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: + case V8ClassIndex::WEBGLINTARRAY: + case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: + case V8ClassIndex::WEBGLFLOATARRAY: { + WebGLArray* array = reinterpret_cast<WebGLArray*>(impl); + setIndexedPropertiesToExternalArray(result, + V8ClassIndex::ToInt(type), + array->baseAddress(), + array->length()); + break; + } + default: + break; + } +#endif + // Special case for non-node objects associated with a // DOMWindow. Both Safari and FF let the JS wrappers for these // objects survive GC. To mimic their behavior, V8 creates @@ -766,13 +948,6 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassI return instance; } -void V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr) -{ - ASSERT(object->InternalFieldCount() >= 2); - object->SetPointerInInternalField(V8Custom::kDOMWrapperObjectIndex, cptr); - object->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type)); -} - #ifndef NDEBUG bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) { @@ -951,7 +1126,7 @@ V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element) #define FOR_EACH_ANIMATION_TAG(macro) #endif -#if ENABLE(SVG_FILTERS) +#if ENABLE(SVG) && ENABLE(FILTERS) #define FOR_EACH_FILTERS_TAG(macro) \ macro(feBlend, FEBLEND) \ macro(feColorMatrix, FECOLORMATRIX) \ @@ -982,7 +1157,6 @@ V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element) #if ENABLE(SVG_FONTS) #define FOR_EACH_FONTS_TAG(macro) \ - macro(definition-src, DEFINITIONSRC) \ macro(font-face, FONTFACE) \ macro(font-face-format, FONTFACEFORMAT) \ macro(font-face-name, FONTFACENAME) \ @@ -1088,8 +1262,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event) type = V8ClassIndex::MOUSEEVENT; else if (event->isWheelEvent()) type = V8ClassIndex::WHEELEVENT; +// ANDROID: Upstream TOUCH_EVENTS. #if ENABLE(TOUCH_EVENTS) - // TODO(andreip): upstream touch related changes to WebKit else if (event->isTouchEvent()) type = V8ClassIndex::TOUCHEVENT; #endif @@ -1097,6 +1271,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event) else if (event->isSVGZoomEvent()) type = V8ClassIndex::SVGZOOMEVENT; #endif + else if (event->isCompositionEvent()) + type = V8ClassIndex::COMPOSITIONEVENT; else type = V8ClassIndex::UIEVENT; } else if (event->isMutationEvent()) @@ -1105,6 +1281,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event) type = V8ClassIndex::OVERFLOWEVENT; else if (event->isMessageEvent()) type = V8ClassIndex::MESSAGEEVENT; + else if (event->isPageTransitionEvent()) + type = V8ClassIndex::PAGETRANSITIONEVENT; else if (event->isProgressEvent()) { if (event->isXMLHttpRequestProgressEvent()) type = V8ClassIndex::XMLHTTPREQUESTPROGRESSEVENT; @@ -1122,6 +1300,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event) else if (event->isStorageEvent()) type = V8ClassIndex::STORAGEEVENT; #endif + else if (event->isBeforeLoadEvent()) + type = V8ClassIndex::BEFORELOADEVENT; v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::EVENT, event); @@ -1155,30 +1335,47 @@ static const V8ClassIndex::V8WrapperType mapping[] = { V8ClassIndex::NODE, // XPATH_NAMESPACE_NODE }; -// Caller checks node is not null. -v8::Handle<v8::Value> V8DOMWrapper::convertNodeToV8Object(Node* node) +v8::Handle<v8::Value> V8DOMWrapper::convertDocumentToV8Object(Document* document) { - if (!node) - return v8::Null(); - // Find a proxy for this node. // // Note that if proxy is found, we might initialize the context which can // instantiate a document wrapper. Therefore, we get the proxy before // checking if the node already has a wrapper. - V8Proxy* proxy = 0; - Document* document = node->document(); - if (document) { - Frame* frame = document->frame(); - proxy = V8Proxy::retrieve(frame); - if (proxy) - proxy->initContextIfNeeded(); - } + V8Proxy* proxy = V8Proxy::retrieve(document->frame()); + if (proxy) + proxy->initContextIfNeeded(); + + DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap(); + v8::Handle<v8::Object> wrapper = domNodeMap.get(document); + if (wrapper.IsEmpty()) + return convertNewNodeToV8Object(document, proxy, domNodeMap); + + return wrapper; +} +v8::Handle<v8::Value> V8DOMWrapper::convertNodeToV8Object(Node* node) +{ + if (!node) + return v8::Null(); + + Document* document = node->document(); + if (node == document) + return convertDocumentToV8Object(document); + DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap(); v8::Handle<v8::Object> wrapper = domNodeMap.get(node); - if (!wrapper.IsEmpty()) - return wrapper; + if (wrapper.IsEmpty()) + return convertNewNodeToV8Object(node, 0, domNodeMap); + + return wrapper; +} + +// Caller checks node is not null. +v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy* proxy, DOMWrapperMap<Node>& domNodeMap) +{ + if (!proxy && node->document()) + proxy = V8Proxy::retrieve(node->document()->frame()); bool isDocument = false; // document type node has special handling V8ClassIndex::V8WrapperType type; @@ -1205,14 +1402,14 @@ v8::Handle<v8::Value> V8DOMWrapper::convertNodeToV8Object(Node* node) else type = V8ClassIndex::DOCUMENT; } else { - ASSERT(nodeType < sizeof(mapping)/sizeof(mapping[0])); + ASSERT(nodeType < static_cast<int>(sizeof(mapping)/sizeof(mapping[0]))); type = mapping[nodeType]; ASSERT(type != V8ClassIndex::INVALID_CLASS_INDEX); } v8::Handle<v8::Context> context; if (proxy) - context = V8Proxy::context(proxy->frame()); + context = proxy->context(); // Enter the node's context and create the wrapper in that context. if (!context.IsEmpty()) @@ -1272,6 +1469,24 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta return convertToV8Object(V8ClassIndex::WORKER, worker); #endif // WORKERS +#if ENABLE(SHARED_WORKERS) + SharedWorker* sharedWorker = target->toSharedWorker(); + if (sharedWorker) + return convertToV8Object(V8ClassIndex::SHAREDWORKER, sharedWorker); +#endif // SHARED_WORKERS + +#if ENABLE(NOTIFICATIONS) + Notification* notification = target->toNotification(); + if (notification) + return convertToV8Object(V8ClassIndex::NOTIFICATION, notification); +#endif + +#if ENABLE(WEB_SOCKETS) + WebSocket* webSocket = target->toWebSocket(); + if (webSocket) + return convertToV8Object(V8ClassIndex::WEBSOCKET, webSocket); +#endif + Node* node = target->toNode(); if (node) return convertNodeToV8Object(node); @@ -1312,14 +1527,83 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta return notHandledByInterceptor(); } -v8::Handle<v8::Value> V8DOMWrapper::convertEventListenerToV8Object(EventListener* listener) +v8::Handle<v8::Value> V8DOMWrapper::convertEventListenerToV8Object(ScriptExecutionContext* context, EventListener* listener) { if (!listener) return v8::Null(); // FIXME: can a user take a lazy event listener and set to other places? V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener); - return v8listener->getListenerObject(); + return v8listener->getListenerObject(context); +} + +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); +} + +#if ENABLE(SVG) +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + return getEventListener(element->correspondingElement(), value, isAttribute, lookup); +} +#endif + +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + if (worker->scriptExecutionContext()->isWorkerContext()) { + WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); + ASSERT(workerContextProxy); + return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); + } + + return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); +} + +#if ENABLE(NOTIFICATIONS) +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + if (notification->scriptExecutionContext()->isWorkerContext()) { + WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); + ASSERT(workerContextProxy); + return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); + } + + return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); +} +#endif + +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + WorkerContextExecutionProxy* workerContextProxy = workerContext->script()->proxy(); + if (workerContextProxy) + return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); + + return 0; +} + +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + return getEventListener(upload->associatedXMLHttpRequest(), value, isAttribute, lookup); +} + +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + if (V8Proxy::retrieve(eventTarget->scriptExecutionContext())) + return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); + +#if ENABLE(WORKERS) + WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); + if (workerContextProxy) + return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); +#endif + + return 0; +} + +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); } v8::Handle<v8::Value> V8DOMWrapper::convertDOMImplementationToV8Object(DOMImplementation* impl) @@ -1485,4 +1769,30 @@ v8::Handle<v8::Value> V8DOMWrapper::convertWindowToV8Object(DOMWindow* window) return global; } +v8::Handle<v8::Value> V8DOMWrapper::convertNamedNodeMapToV8Object(NamedNodeMap* map) +{ + if (!map) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(map); + if (!wrapper.IsEmpty()) + return wrapper; + + v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::NAMEDNODEMAP, V8ClassIndex::NAMEDNODEMAP, map); + if (result.IsEmpty()) + return result; + + // Only update the DOM object map if the result is non-empty. + map->ref(); + setJSWrapperForDOMObject(map, v8::Persistent<v8::Object>::New(result)); + + // Add a hidden reference from named node map to its owner node. + if (Element* element = map->element()) { + v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(element)); + result->SetInternalField(V8Custom::kNamedNodeMapOwnerNodeIndex, owner); + } + + return result; +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h index 57b3a69..660b827 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.h +++ b/WebCore/bindings/v8/V8DOMWrapper.h @@ -31,13 +31,18 @@ #ifndef V8DOMWrapper_h #define V8DOMWrapper_h +#include "Document.h" #include "Event.h" #include "Node.h" #include "NodeFilter.h" #include "PlatformString.h" // for WebCore::String #include "V8CustomBinding.h" +#include "V8CustomXPathNSResolver.h" +#include "V8DOMMap.h" #include "V8Index.h" #include "V8Utilities.h" +#include "V8XPathNSResolver.h" +#include "XPathNSResolver.h" #include <v8.h> namespace WebCore { @@ -86,8 +91,16 @@ namespace WebCore { class StyleSheetList; class V8EventListener; class V8ObjectEventListener; +#if ENABLE(WEB_SOCKETS) + class WebSocket; +#endif class WorkerContext; + enum ListenerLookupType { + ListenerFindOnly, + ListenerFindOrCreate, + }; + class V8DOMWrapper { public: #ifndef NDEBUG @@ -96,7 +109,12 @@ namespace WebCore { #endif // Sets contents of a DOM wrapper. - static void setDOMWrapper(v8::Handle<v8::Object>, int type, void* ptr); + static void setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr) + { + ASSERT(object->InternalFieldCount() >= 2); + object->SetPointerInInternalField(V8Custom::kDOMWrapperObjectIndex, cptr); + object->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type)); + } static v8::Handle<v8::Object> lookupDOMWrapper(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) { @@ -136,6 +154,20 @@ namespace WebCore { static v8::Handle<v8::Value> convertNodeToV8Object(Node*); + static v8::Handle<v8::Value> convertDocumentToV8Object(Document*); + + static v8::Handle<v8::Value> convertNewNodeToV8Object(PassRefPtr<Node> node) + { + return convertNewNodeToV8Object(node.get()); + } + + static v8::Handle<v8::Value> convertNewNodeToV8Object(Node* node) + { + return convertNewNodeToV8Object(node, 0, getDOMNodeMap()); + } + + static v8::Handle<v8::Value> convertNewNodeToV8Object(Node*, V8Proxy*, DOMWrapperMap<Node>&); + template <class C> static C* convertToNativeObject(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) { @@ -184,12 +216,47 @@ namespace WebCore { static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*); // Wrap and unwrap JS event listeners. - static v8::Handle<v8::Value> convertEventListenerToV8Object(PassRefPtr<Event> eventListener) + static v8::Handle<v8::Value> convertEventListenerToV8Object(ScriptExecutionContext* context, PassRefPtr<EventListener> eventListener) { - return convertEventListenerToV8Object(eventListener.get()); + return convertEventListenerToV8Object(context, eventListener.get()); } - static v8::Handle<v8::Value> convertEventListenerToV8Object(EventListener*); + static v8::Handle<v8::Value> convertEventListenerToV8Object(ScriptExecutionContext*, EventListener*); + + static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + + static PassRefPtr<EventListener> getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + + static PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + +#if ENABLE(NOTIFICATIONS) + static PassRefPtr<EventListener> getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); +#endif + + static PassRefPtr<EventListener> getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + + static PassRefPtr<EventListener> getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + + static PassRefPtr<EventListener> getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + + static PassRefPtr<EventListener> getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + + +#if PLATFORM(ANDROID) +// TODO: upstream XPATH guard. +#if ENABLE(XPATH) + // XPath-related utilities + static RefPtr<XPathNSResolver> getXPathNSResolver(v8::Handle<v8::Value> value, V8Proxy* proxy = 0) + { + RefPtr<XPathNSResolver> resolver; + if (V8XPathNSResolver::HasInstance(value)) + resolver = convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(value)); + else if (value->IsObject()) + resolver = V8CustomXPathNSResolver::create(proxy, value->ToObject()); + return resolver; + } +#endif +#endif // DOMImplementation is a singleton and it is handled in a special // way. A wrapper is generated per document and stored in an @@ -207,6 +274,10 @@ namespace WebCore { // Checks whether a DOM object has a JS wrapper. static bool domObjectHasJSWrapper(void*); + // Get JS wrapper of an existing DOM object, assuming that the wrapper + // exists. + static v8::Persistent<v8::Object> jsWrapperForDOMObject(void*); + static v8::Persistent<v8::Object> jsWrapperForActiveDOMObject(void*); // Set JS wrapper of a DOM object, the caller in charge of increase ref. static void setJSWrapperForDOMObject(void*, v8::Persistent<v8::Object>); static void setJSWrapperForActiveDOMObject(void*, v8::Persistent<v8::Object>); @@ -226,12 +297,20 @@ namespace WebCore { // Returns the JS wrapper of a window object, initializes the environment // of the window frame if needed. static v8::Handle<v8::Value> convertWindowToV8Object(DOMWindow*); + static v8::Handle<v8::Value> convertNamedNodeMapToV8Object(NamedNodeMap*); #if ENABLE(SVG) static v8::Handle<v8::Value> convertSVGElementInstanceToV8Object(SVGElementInstance*); static v8::Handle<v8::Value> convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType, void*); #endif +#if ENABLE(3D_CANVAS) + static void setIndexedPropertiesToExternalArray(v8::Handle<v8::Object>, + int, + void*, + int); +#endif + private: // Set hidden references in a DOMWindow object of a frame. static void setHiddenWindowReference(Frame*, const int internalIndex, v8::Handle<v8::Object>); diff --git a/WebCore/bindings/v8/V8EventListenerList.cpp b/WebCore/bindings/v8/V8EventListenerList.cpp index c9aaa12..e37d630 100644 --- a/WebCore/bindings/v8/V8EventListenerList.cpp +++ b/WebCore/bindings/v8/V8EventListenerList.cpp @@ -31,165 +31,6 @@ #include "config.h" #include "V8EventListenerList.h" -#include "V8CustomEventListener.h" - namespace WebCore { -V8EventListenerListIterator::V8EventListenerListIterator(V8EventListenerList* list) - : m_list(list) - , m_vectorIndex(0) - , m_iter(list->m_table.begin()) -{ -} - -V8EventListenerListIterator::V8EventListenerListIterator(V8EventListenerList* list, bool shouldSeekToEnd) - : m_list(list) - , m_vectorIndex(0) - , m_iter(list->m_table.begin()) -{ - if (shouldSeekToEnd) - seekToEnd(); -} - -V8EventListenerListIterator::~V8EventListenerListIterator() { } - -void V8EventListenerListIterator::operator++() -{ - if (m_iter != m_list->m_table.end()) { - Vector<V8EventListener*>* vector = m_iter->second; - if (m_vectorIndex + 1 < vector->size()) { - m_vectorIndex++; - return; - } - m_vectorIndex = 0; - ++m_iter; - } -} - -bool V8EventListenerListIterator::operator==(const V8EventListenerListIterator& other) -{ - return other.m_iter == m_iter && other.m_vectorIndex == m_vectorIndex && other.m_list == m_list; -} - -bool V8EventListenerListIterator::operator!=(const V8EventListenerListIterator& other) -{ - return !operator==(other); -} - -V8EventListener* V8EventListenerListIterator::operator*() -{ - if (m_iter != m_list->m_table.end()) { - Vector<V8EventListener*>* vector = m_iter->second; - if (m_vectorIndex < vector->size()) - return vector->at(m_vectorIndex); - } - return 0; -} - -void V8EventListenerListIterator::seekToEnd() -{ - m_iter = m_list->m_table.end(); - m_vectorIndex = 0; -} - - -V8EventListenerList::V8EventListenerList() -{ -} - -V8EventListenerList::~V8EventListenerList() -{ -} - -V8EventListenerListIterator V8EventListenerList::begin() -{ - return iterator(this); -} - -V8EventListenerListIterator V8EventListenerList::end() -{ - return iterator(this, true); -} - - -static int getKey(v8::Local<v8::Object> object) -{ - // 0 is a sentinel value for the HashMap key, so we map it to 1. - int hash = object->GetIdentityHash(); - if (!hash) - return 1; - return hash; -} - -void V8EventListenerList::add(V8EventListener* listener) -{ - ASSERT(v8::Context::InContext()); - v8::HandleScope handleScope; - - v8::Local<v8::Object> object = listener->getListenerObject(); - int key = getKey(object); - Vector<V8EventListener*>* vector = m_table.get(key); - if (!vector) { - vector = new Vector<V8EventListener*>(); - m_table.set(key, vector); - } - vector->append(listener); - m_reverseTable.set(listener, key); -} - -void V8EventListenerList::remove(V8EventListener* listener) -{ - if (m_reverseTable.contains(listener)) { - int key = m_reverseTable.get(listener); - Vector<V8EventListener*>* vector = m_table.get(key); - if (!vector) - return; - for (size_t j = 0; j < vector->size(); j++) { - if (vector->at(j) == listener) { - vector->remove(j); - if (!vector->size()) { - m_table.remove(key); - delete vector; - vector = 0; - } - m_reverseTable.remove(listener); - return; - } - } - } -} - -void V8EventListenerList::clear() -{ - m_table.clear(); - m_reverseTable.clear(); -} - -V8EventListener* V8EventListenerList::find(v8::Local<v8::Object> object, bool isAttribute) -{ - ASSERT(v8::Context::InContext()); - int key = getKey(object); - - Vector<V8EventListener*>* vector = m_table.get(key); - if (!vector) - return 0; - - for (size_t i = 0; i < vector->size(); i++) { - V8EventListener* element = vector->at(i); - if (isAttribute == element->isAttribute() && object == element->getListenerObject()) - return element; - } - return 0; -} - -PassRefPtr<V8EventListener> V8EventListenerList::findWrapper(v8::Local<v8::Value> object, bool isAttribute) -{ - ASSERT(v8::Context::InContext()); - if (!object->IsObject()) - return 0; - - // FIXME: Should this be v8::Local<v8::Object>::Cast instead? - return find(object->ToObject(), isAttribute); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/V8EventListenerList.h b/WebCore/bindings/v8/V8EventListenerList.h index 4255050..fdf211d 100644 --- a/WebCore/bindings/v8/V8EventListenerList.h +++ b/WebCore/bindings/v8/V8EventListenerList.h @@ -31,93 +31,74 @@ #ifndef V8EventListenerList_h #define V8EventListenerList_h -#include <v8.h> -#include <wtf/Vector.h> -#include <wtf/HashMap.h> +#include "V8CustomEventListener.h" +#include "V8HiddenPropertyName.h" -#include "PassRefPtr.h" +#include <v8.h> +#include <wtf/PassRefPtr.h> namespace WebCore { class Frame; - class V8EventListener; - class V8EventListenerListIterator; - // This is a container for V8EventListener objects that uses the identity hash of the v8::Object to - // speed up lookups + // This is a container for V8EventListener objects that uses hidden properties of v8::Object to speed up lookups. class V8EventListenerList { public: - // Because v8::Object identity hashes are not guaranteed to be unique, we unfortunately can't just map - // an int to V8EventListener. Instead we define a HashMap of int to Vector of V8EventListener - // called a ListenerMultiMap. - typedef Vector<V8EventListener*>* Values; - struct ValuesTraits : HashTraits<Values> { - static const bool needsDestruction = true; - }; - typedef HashMap<int, Values, DefaultHash<int>::Hash, HashTraits<int>, ValuesTraits> ListenerMultiMap; - - V8EventListenerList(); - ~V8EventListenerList(); - - friend class V8EventListenerListIterator; - typedef V8EventListenerListIterator iterator; - - iterator begin(); - iterator end(); - - void add(V8EventListener*); - void remove(V8EventListener*); - V8EventListener* find(v8::Local<v8::Object>, bool isAttribute); - void clear(); - size_t size() { return m_table.size(); } - - PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value>, bool isAttribute); - template<typename WrapperType> - PassRefPtr<V8EventListener> findOrCreateWrapper(Frame*, v8::Local<v8::Value>, bool isAttribute); + static PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value> value, bool isAttribute) + { + ASSERT(v8::Context::InContext()); + if (!value->IsObject()) + return 0; - private: - ListenerMultiMap m_table; + v8::Handle<v8::String> wrapperProperty = getHiddenProperty(isAttribute); + return doFindWrapper(v8::Local<v8::Object>::Cast(value), wrapperProperty); + } - // we also keep a reverse mapping of V8EventListener to v8::Object identity hash, - // in order to speed up removal by V8EventListener - HashMap<V8EventListener*, int> m_reverseTable; - }; + template<typename WrapperType> + static PassRefPtr<V8EventListener> findOrCreateWrapper(v8::Local<v8::Value>, bool isAttribute); + + static void clearWrapper(v8::Handle<v8::Object> listenerObject, bool isAttribute) + { + v8::Handle<v8::String> wrapperProperty = getHiddenProperty(isAttribute); + listenerObject->DeleteHiddenValue(wrapperProperty); + } - class V8EventListenerListIterator { - public: - ~V8EventListenerListIterator(); - void operator++(); - bool operator==(const V8EventListenerListIterator&); - bool operator!=(const V8EventListenerListIterator&); - V8EventListener* operator*(); private: - friend class V8EventListenerList; - explicit V8EventListenerListIterator(V8EventListenerList*); - V8EventListenerListIterator(V8EventListenerList*, bool shouldSeekToEnd); - void seekToEnd(); - - V8EventListenerList* m_list; - V8EventListenerList::ListenerMultiMap::iterator m_iter; - size_t m_vectorIndex; + static V8EventListener* doFindWrapper(v8::Local<v8::Object> object, v8::Handle<v8::String> wrapperProperty) + { + ASSERT(v8::Context::InContext()); + v8::HandleScope scope; + v8::Local<v8::Value> listener = object->GetHiddenValue(wrapperProperty); + if (listener.IsEmpty()) + return 0; + return static_cast<V8EventListener*>(v8::External::Unwrap(listener)); + } + + static inline v8::Handle<v8::String> getHiddenProperty(bool isAttribute) + { + return isAttribute ? V8HiddenPropertyName::attributeListener() : V8HiddenPropertyName::listener(); + } }; template<typename WrapperType> - PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(Frame* frame, v8::Local<v8::Value> object, bool isAttribute) + PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(v8::Local<v8::Value> value, bool isAttribute) { ASSERT(v8::Context::InContext()); - if (!object->IsObject()) + if (!value->IsObject()) return 0; - // FIXME: Should this be v8::Local<v8::Object>::Cast instead? - V8EventListener* wrapper = find(object->ToObject(), isAttribute); + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); + v8::Handle<v8::String> wrapperProperty = getHiddenProperty(isAttribute); + + V8EventListener* wrapper = doFindWrapper(object, wrapperProperty); if (wrapper) return wrapper; - // Create a new one, and add to cache. - RefPtr<WrapperType> newListener = WrapperType::create(frame, v8::Local<v8::Object>::Cast(object), isAttribute); - add(newListener.get()); + PassRefPtr<V8EventListener> wrapperPtr = WrapperType::create(object, isAttribute, WorldContextHandle(UseCurrentWorld)); + if (wrapperPtr) + object->SetHiddenValue(wrapperProperty, v8::External::Wrap(wrapperPtr.get())); - return newListener; - }; + return wrapperPtr; + } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8GCController.cpp b/WebCore/bindings/v8/V8GCController.cpp index f3b1376..b478636 100644 --- a/WebCore/bindings/v8/V8GCController.cpp +++ b/WebCore/bindings/v8/V8GCController.cpp @@ -204,35 +204,11 @@ public: // has the drawback that the wrappers are "entangled/unentangled" for each // GC even though their entaglement most likely is still the same. if (type == V8ClassIndex::MESSAGEPORT) { - // Get the port and its entangled port. + // Mark each port as in-use if it's entangled. For simplicity's sake, we assume all ports are remotely entangled, + // since the Chromium port implementation can't tell the difference. MessagePort* port1 = static_cast<MessagePort*>(object); - MessagePort* port2 = port1->locallyEntangledPort(); - - // If we are remotely entangled, then mark this object as reachable - // (we can't determine reachability directly as the remote object is - // out-of-proc). - if (port1->isEntangled() && !port2) + if (port1->isEntangled()) wrapper.ClearWeak(); - - if (port2) { - // As ports are always entangled in pairs only perform the entanglement - // once for each pair (see ASSERT in MessagePort::unentangle()). - if (port1 < port2) { - v8::Handle<v8::Value> port1Wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port1); - v8::Handle<v8::Value> port2Wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port2); - ASSERT(port1Wrapper->IsObject()); - v8::Handle<v8::Object>::Cast(port1Wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, port2Wrapper); - ASSERT(port2Wrapper->IsObject()); - v8::Handle<v8::Object>::Cast(port2Wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, port1Wrapper); - } - } else { - // Remove the wrapper entanglement when a port is not entangled. - if (V8DOMWrapper::domObjectHasJSWrapper(port1)) { - v8::Handle<v8::Value> wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port1); - ASSERT(wrapper->IsObject()); - v8::Handle<v8::Object>::Cast(wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, v8::Undefined()); - } - } } } }; @@ -263,16 +239,6 @@ bool operator<(const GrouperItem& a, const GrouperItem& b) typedef Vector<GrouperItem> GrouperList; -#if PLATFORM(ANDROID) -// Sort GrouperList by the group id. Node* is only involved to sort within -// a group id, so it will be fine. -// TODO(andreip): used by std::stable_sort function. We can implement -// the std::sort function and remove this one. -static bool compareGrouperItem(const GrouperItem& a, const GrouperItem& b) { - return a.groupId() < b.groupId(); -} -#endif - class ObjectGrouperVisitor : public DOMWrapperMap<Node>::Visitor { public: ObjectGrouperVisitor() @@ -296,14 +262,21 @@ public: groupId = reinterpret_cast<uintptr_t>(node->document()); else { Node* root = node; - while (root->parent()) - root = root->parent(); - - // If the node is alone in its DOM tree (doesn't have a parent or any - // children) then the group will be filtered out later anyway. - if (root == node && !node->hasChildNodes()) - return; - + if (node->isAttributeNode()) { + root = static_cast<Attr*>(node)->ownerElement(); + // If the attribute has no element, no need to put it in the group, + // because it'll always be a group of 1. + if (!root) + return; + } else { + while (root->parent()) + root = root->parent(); + + // If the node is alone in its DOM tree (doesn't have a parent or any + // children) then the group will be filtered out later anyway. + if (root == node && !node->hasChildNodes() && !node->hasAttributes()) + return; + } groupId = reinterpret_cast<uintptr_t>(root); } m_grouper.append(GrouperItem(groupId, node, wrapper)); @@ -311,13 +284,8 @@ public: void applyGrouping() { -#if PLATFORM(ANDROID) - // TODO(andreip): implement std::sort() and get rid of this. - std::stable_sort<GrouperItem>(m_grouper.begin(), m_grouper.end(), compareGrouperItem); -#else // Group by sorting by the group id. std::sort(m_grouper.begin(), m_grouper.end()); -#endif // FIXME Should probably work in iterators here, but indexes were easier for my simple mind. for (size_t i = 0; i < m_grouper.size(); ) { @@ -342,7 +310,6 @@ public: Vector<v8::Persistent<v8::Value> > group; group.reserveCapacity(nextKeyIndex - i); for (; i < nextKeyIndex; ++i) { - Node* node = m_grouper[i].node(); v8::Persistent<v8::Value> wrapper = m_grouper[i].wrapper(); if (!wrapper.IsEmpty()) group.append(wrapper); @@ -421,17 +388,30 @@ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) if (type == V8ClassIndex::MESSAGEPORT) { MessagePort* port1 = static_cast<MessagePort*>(object); - MessagePort* port2 = port1->locallyEntangledPort(); - if (port1->isEntangled() && !port2) { - // We marked this port as reachable in GCPrologueVisitor. Undo this now since the - // port could be not reachable in the future if it gets disentangled (and also - // GCPrologueVisitor expects to see all handles marked as weak). + // We marked this port as reachable in GCPrologueVisitor. Undo this now since the + // port could be not reachable in the future if it gets disentangled (and also + // GCPrologueVisitor expects to see all handles marked as weak). + if (!wrapper.IsWeak() && !wrapper.IsNearDeath()) wrapper.MakeWeak(port1, &DOMDataStore::weakActiveDOMObjectCallback); - } } } }; +int V8GCController::workingSetEstimateMB = 0; + +namespace { + +int getMemoryUsageInMB() +{ +#if PLATFORM(CHROMIUM) + return ChromiumBridge::memoryUsageMB(); +#else + return 0; +#endif +} + +} // anonymous namespace + void V8GCController::gcEpilogue() { v8::HandleScope scope; @@ -441,6 +421,8 @@ void V8GCController::gcEpilogue() GCEpilogueVisitor epilogueVisitor; visitActiveDOMObjectsInCurrentThread(&epilogueVisitor); + workingSetEstimateMB = getMemoryUsageInMB(); + #ifndef NDEBUG // Check all survivals are weak. DOMObjectVisitor domObjectVisitor; @@ -454,4 +436,19 @@ void V8GCController::gcEpilogue() #endif } +void V8GCController::checkMemoryUsage() +{ +#if PLATFORM(CHROMIUM) + // These values are appropriate for Chromium only. + const int lowUsageMB = 256; // If memory usage is below this threshold, do not bother forcing GC. + const int highUsageMB = 1024; // If memory usage is above this threshold, force GC more aggresively. + const int highUsageDeltaMB = 128; // Delta of memory usage growth (vs. last workingSetEstimateMB) to force GC when memory usage is high. + + int memoryUsageMB = getMemoryUsageInMB(); + if ((memoryUsageMB > lowUsageMB && memoryUsageMB > 2 * workingSetEstimateMB) || (memoryUsageMB > highUsageMB && memoryUsageMB > workingSetEstimateMB + highUsageDeltaMB)) + v8::V8::LowMemoryNotification(); +#endif +} + + } // namespace WebCore diff --git a/WebCore/bindings/v8/V8GCController.h b/WebCore/bindings/v8/V8GCController.h index 7441bf0..484be24 100644 --- a/WebCore/bindings/v8/V8GCController.h +++ b/WebCore/bindings/v8/V8GCController.h @@ -78,6 +78,12 @@ namespace WebCore { static void gcPrologue(); static void gcEpilogue(); + + static void checkMemoryUsage(); + + private: + // Estimate of current working set. + static int workingSetEstimateMB; }; } diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.cpp b/WebCore/bindings/v8/V8HiddenPropertyName.cpp index 16ac232..d83573f 100644 --- a/WebCore/bindings/v8/V8HiddenPropertyName.cpp +++ b/WebCore/bindings/v8/V8HiddenPropertyName.cpp @@ -33,22 +33,21 @@ namespace WebCore { -v8::Handle<v8::String> V8HiddenPropertyName::objectPrototype() -{ - static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::objectPrototype"); - - return *string; +#define V8_AS_STRING(x) V8_AS_STRING_IMPL(x) +#define V8_AS_STRING_IMPL(x) #x + +#define V8_DEFINE_PROPERTY(name) \ +v8::Handle<v8::String> V8HiddenPropertyName::name() \ +{ \ + static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::" V8_AS_STRING(name)); \ + return *string; \ } -v8::Handle<v8::String> V8HiddenPropertyName::isolatedWorld() -{ - static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::isolatedWorld"); - - return *string; -} +V8_HIDDEN_PROPERTIES(V8_DEFINE_PROPERTY); v8::Persistent<v8::String>* V8HiddenPropertyName::createString(const char* key) { + v8::HandleScope scope; return new v8::Persistent<v8::String>(v8::Persistent<v8::String>::New(v8::String::NewSymbol(key))); } diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.h b/WebCore/bindings/v8/V8HiddenPropertyName.h index 874b525..bb1ca4c 100644 --- a/WebCore/bindings/v8/V8HiddenPropertyName.h +++ b/WebCore/bindings/v8/V8HiddenPropertyName.h @@ -35,10 +35,18 @@ namespace WebCore { +#define V8_HIDDEN_PROPERTIES(V) \ + V(objectPrototype) \ + V(listener) \ + V(attributeListener) \ + V(sleepFunction) \ + V(toStringString) + class V8HiddenPropertyName { public: - static v8::Handle<v8::String> objectPrototype(); - static v8::Handle<v8::String> isolatedWorld(); +#define V8_DECLARE_PROPERTY(name) static v8::Handle<v8::String> name(); + V8_HIDDEN_PROPERTIES(V8_DECLARE_PROPERTY); +#undef V8_DECLARE_PROPERTY private: static v8::Persistent<v8::String>* createString(const char* key); diff --git a/WebCore/bindings/v8/V8Index.cpp b/WebCore/bindings/v8/V8Index.cpp index 9efbc3d..9686dc6 100644 --- a/WebCore/bindings/v8/V8Index.cpp +++ b/WebCore/bindings/v8/V8Index.cpp @@ -33,6 +33,9 @@ #include "V8Attr.h" #include "V8BarInfo.h" +#include "V8BeforeLoadEvent.h" +#include "V8WebGLActiveInfo.h" +#include "V8CanvasRenderingContext.h" #include "V8CanvasRenderingContext2D.h" #include "V8CanvasGradient.h" #include "V8CanvasPattern.h" @@ -43,6 +46,7 @@ #include "V8ClientRectList.h" #include "V8Clipboard.h" #include "V8Comment.h" +#include "V8CompositionEvent.h" #include "V8Console.h" #include "V8Counter.h" #include "V8CSSStyleDeclaration.h" @@ -107,6 +111,7 @@ #include "V8HTMLHtmlElement.h" #include "V8HTMLIFrameElement.h" #include "V8HTMLImageElement.h" +#include "V8HTMLImageElementConstructor.h" #include "V8HTMLInputElement.h" #include "V8HTMLIsIndexElement.h" #include "V8HTMLLabelElement.h" @@ -121,6 +126,7 @@ #include "V8HTMLOListElement.h" #include "V8HTMLOptGroupElement.h" #include "V8HTMLOptionElement.h" +#include "V8HTMLOptionElementConstructor.h" #include "V8HTMLParagraphElement.h" #include "V8HTMLParamElement.h" #include "V8HTMLPreElement.h" @@ -179,6 +185,7 @@ #include "V8Navigator.h" #include "V8MimeType.h" #include "V8MimeTypeArray.h" +#include "V8PageTransitionEvent.h" #include "V8Plugin.h" #include "V8PluginArray.h" #include "V8Range.h" @@ -195,24 +202,11 @@ #include "V8XMLHttpRequestUpload.h" #include "V8XMLSerializer.h" #include "V8RGBColor.h" -#include "V8VoidCallback.h" - -#if !PLATFORM(ANDROID) -#include "V8InspectorBackend.h" -#endif #if ENABLE(OFFLINE_WEB_APPLICATIONS) #include "V8DOMApplicationCache.h" #endif -#if ENABLE(DATABASE) -#include "V8Database.h" -#include "V8SQLError.h" -#include "V8SQLResultSet.h" -#include "V8SQLResultSetRowList.h" -#include "V8SQLTransaction.h" -#endif - #if ENABLE(DOM_STORAGE) #include "V8Storage.h" #include "V8StorageEvent.h" @@ -226,7 +220,7 @@ #include "V8SVGSetElement.h" #endif -#if ENABLE(SVG_FILTERS) +#if ENABLE(SVG) && ENABLE(FILTERS) #include "V8SVGComponentTransferFunctionElement.h" #include "V8SVGFEBlendElement.h" #include "V8SVGFEColorMatrixElement.h" @@ -244,6 +238,7 @@ #include "V8SVGFEImageElement.h" #include "V8SVGFEMergeElement.h" #include "V8SVGFEMergeNodeElement.h" +#include "V8SVGFEMorphologyElement.h" #include "V8SVGFEOffsetElement.h" #include "V8SVGFEPointLightElement.h" #include "V8SVGFESpecularLightingElement.h" @@ -254,7 +249,6 @@ #endif #if ENABLE(SVG_FONTS) -#include "V8SVGDefinitionSrcElement.h" #include "V8SVGFontFaceElement.h" #include "V8SVGFontFaceFormatElement.h" #include "V8SVGFontFaceNameElement.h" @@ -364,12 +358,12 @@ #include "V8SVGTransform.h" #include "V8SVGTransformList.h" #include "V8SVGUnitTypes.h" -#include "V8SVGURIReference.h" #include "V8SVGZoomEvent.h" #endif #if ENABLE(VIDEO) #include "V8HTMLAudioElement.h" +#include "V8HTMLAudioElementConstructor.h" #include "V8HTMLMediaElement.h" #include "V8HTMLSourceElement.h" #include "V8HTMLVideoElement.h" @@ -377,6 +371,10 @@ #include "V8TimeRanges.h" #endif +#if ENABLE(WEB_SOCKETS) +#include "V8WebSocket.h" +#endif + #if ENABLE(WORKERS) #include "V8AbstractWorker.h" #include "V8DedicatedWorkerContext.h" @@ -386,35 +384,79 @@ #include "V8WorkerNavigator.h" #endif +#if ENABLE(NOTIFICATIONS) +#include "V8Notification.h" +#include "V8NotificationCenter.h" +#endif + #if ENABLE(SHARED_WORKERS) #include "V8SharedWorker.h" +#include "V8SharedWorkerContext.h" #endif -#if ENABLE(GEOLOCATION) -#include "V8Coordinates.h" -#include "V8Geolocation.h" -#include "V8Geoposition.h" -#include "V8PositionError.h" +#if ENABLE(3D_CANVAS) +#include "V8WebGLRenderingContext.h" +#include "V8WebGLArrayBuffer.h" +#include "V8WebGLArray.h" +#include "V8WebGLByteArray.h" +#include "V8WebGLBuffer.h" +#include "V8WebGLFloatArray.h" +#include "V8WebGLFramebuffer.h" +#include "V8WebGLIntArray.h" +#include "V8WebGLProgram.h" +#include "V8WebGLRenderbuffer.h" +#include "V8WebGLShader.h" +#include "V8WebGLShortArray.h" +#include "V8WebGLTexture.h" +#include "V8WebGLUniformLocation.h" +#include "V8WebGLUnsignedByteArray.h" +#include "V8WebGLUnsignedIntArray.h" +#include "V8WebGLUnsignedShortArray.h" #endif -#if ENABLE(TOUCH_EVENTS) -#include "V8Touch.h" -#include "V8TouchList.h" -#include "V8TouchEvent.h" +#if ENABLE(DATABASE) +#include "V8Database.h" +#include "V8SQLError.h" +#include "V8SQLResultSet.h" +#include "V8SQLResultSetRowList.h" +#include "V8SQLTransaction.h" #endif #if ENABLE(XPATH) #include "V8XPathResult.h" #include "V8XPathException.h" #include "V8XPathExpression.h" -#include "V8XPathEvaluator.h" #include "V8XPathNSResolver.h" +#include "V8XPathEvaluator.h" #endif #if ENABLE(XSLT) #include "V8XSLTProcessor.h" #endif +#if ENABLE(INSPECTOR) +#include "V8InjectedScriptHost.h" +#include "V8InspectorBackend.h" +#include "V8InspectorFrontendHost.h" +#endif + +// Geolocation +#include "V8Coordinates.h" +#include "V8Geolocation.h" +#include "V8Geoposition.h" +#include "V8PositionError.h" + +#if PLATFORM(ANDROID) +// TODO: Upstream these guards to webkit.org +#if ENABLE(TOUCH_EVENTS) +#include "V8Touch.h" +#include "V8TouchList.h" +#include "V8TouchEvent.h" +#endif + +#include "V8VoidCallback.h" +#endif // PLATFORM(ANDROID) + namespace WebCore { FunctionTemplateFactory V8ClassIndex::GetFactory(V8WrapperType type) diff --git a/WebCore/bindings/v8/V8Index.h b/WebCore/bindings/v8/V8Index.h index d6db4c6..d786aab 100644 --- a/WebCore/bindings/v8/V8Index.h +++ b/WebCore/bindings/v8/V8Index.h @@ -54,6 +54,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #if ENABLE(VIDEO) #define VIDEO_HTMLELEMENT_TYPES(V) \ + V(AUDIO, HTMLAudioElementConstructor) \ V(HTMLAUDIOELEMENT, HTMLAudioElement) \ V(HTMLMEDIAELEMENT, HTMLMediaElement) \ V(HTMLSOURCEELEMENT, HTMLSourceElement) \ @@ -82,16 +83,26 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #endif #if ENABLE(OFFLINE_WEB_APPLICATIONS) -#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ +#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ V(DOMAPPLICATIONCACHE, DOMApplicationCache) #else #define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) #endif +#if ENABLE(NOTIFICATIONS) +#define NOTIFICATIONS_NONNODE_WRAPPER_TYPES(V) \ + V(NOTIFICATION, Notification) \ + V(NOTIFICATIONCENTER, NotificationCenter) +#else +#define NOTIFICATIONS_NONNODE_WRAPPER_TYPES(V) +#endif + #if ENABLE(SHARED_WORKERS) #define SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ V(SHAREDWORKER, SharedWorker) -#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) + +#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) \ + V(SHAREDWORKERCONTEXT, SharedWorkerContext) #else #define SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) #define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) @@ -109,7 +120,9 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(ENTITY, Entity) \ V(ENTITYREFERENCE, EntityReference) \ V(HTMLDOCUMENT, HTMLDocument) \ + V(IMAGE, HTMLImageElementConstructor) \ V(NODE, Node) \ + V(OPTION, HTMLOptionElementConstructor) \ V(NOTATION, Notation) \ V(PROCESSINGINSTRUCTION, ProcessingInstruction) \ V(TEXT, Text) \ @@ -184,7 +197,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #define SVG_ANIMATION_ELEMENT_TYPES(V) #endif -#if ENABLE(SVG_FILTERS) +#if ENABLE(SVG) && ENABLE(FILTERS) #define SVG_FILTERS_ELEMENT_TYPES(V) \ V(SVGCOMPONENTTRANSFERFUNCTIONELEMENT, SVGComponentTransferFunctionElement)\ V(SVGFEBLENDELEMENT, SVGFEBlendElement) \ @@ -203,6 +216,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(SVGFEIMAGEELEMENT, SVGFEImageElement) \ V(SVGFEMERGEELEMENT, SVGFEMergeElement) \ V(SVGFEMERGENODEELEMENT, SVGFEMergeNodeElement) \ + V(SVGFEMORPHOLOGYELEMENT, SVGFEMorphologyElement) \ V(SVGFEOFFSETELEMENT, SVGFEOffsetElement) \ V(SVGFEPOINTLIGHTELEMENT, SVGFEPointLightElement) \ V(SVGFESPECULARLIGHTINGELEMENT, SVGFESpecularLightingElement) \ @@ -216,7 +230,6 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #if ENABLE(SVG_FONTS) #define SVG_FONTS_ELEMENT_TYPES(V) \ - V(SVGDEFINITIONSRCELEMENT, SVGDefinitionSrcElement) \ V(SVGFONTFACEELEMENT, SVGFontFaceElement) \ V(SVGFONTFACEFORMATELEMENT, SVGFontFaceFormatElement) \ V(SVGFONTFACENAMEELEMENT, SVGFontFaceNameElement) \ @@ -289,13 +302,21 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #endif // SVG +#if ENABLE(WEB_SOCKETS) +#define WEBSOCKET_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + V(WEBSOCKET, WebSocket) +#else +#define WEBSOCKET_ACTIVE_OBJECT_WRAPPER_TYPES(V) +#endif + // ACTIVE_DOM_OBJECT_TYPES are DOM_OBJECT_TYPES that need special treatement // during GC. #define ACTIVE_DOM_OBJECT_TYPES(V) \ V(MESSAGEPORT, MessagePort) \ V(XMLHTTPREQUEST, XMLHttpRequest) \ WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ - SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) + SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + WEBSOCKET_ACTIVE_OBJECT_WRAPPER_TYPES(V) // NOTE: DOM_OBJECT_TYPES is split into two halves because // Visual Studio's Intellinonsense crashes when macros get @@ -303,13 +324,16 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); // DOM_OBJECT_TYPES are non-node DOM types. #define DOM_OBJECT_TYPES_1(V) \ V(BARINFO, BarInfo) \ + V(BEFORELOADEVENT, BeforeLoadEvent) \ V(CANVASGRADIENT, CanvasGradient) \ V(CANVASPATTERN, CanvasPattern) \ + V(CANVASRENDERINGCONTEXT, CanvasRenderingContext) \ V(CANVASRENDERINGCONTEXT2D, CanvasRenderingContext2D) \ V(CLIENTRECT, ClientRect) \ V(CLIENTRECTLIST, ClientRectList) \ V(CLIPBOARD, Clipboard) \ V(CONSOLE, Console) \ + V(COMPOSITIONEVENT, CompositionEvent) \ V(COUNTER, Counter) \ V(CSSCHARSETRULE, CSSCharsetRule) \ V(CSSFONTFACERULE, CSSFontFaceRule) \ @@ -359,6 +383,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(NODEITERATOR, NodeIterator) \ V(NODELIST, NodeList) \ V(OVERFLOWEVENT, OverflowEvent) \ + V(PAGETRANSITIONEVENT, PageTransitionEvent) \ V(PLUGIN, Plugin) \ V(PLUGINARRAY, PluginArray) \ V(PROGRESSEVENT, ProgressEvent) \ @@ -374,7 +399,6 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(TREEWALKER, TreeWalker) \ V(UIEVENT, UIEvent) \ V(VALIDITYSTATE, ValidityState) \ - V(VOIDCALLBACK, VoidCallback) \ V(WEBKITANIMATIONEVENT, WebKitAnimationEvent) \ V(WEBKITCSSKEYFRAMERULE, WebKitCSSKeyframeRule) \ V(WEBKITCSSKEYFRAMESRULE, WebKitCSSKeyframesRule) \ @@ -391,27 +415,10 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ DATAGRID_NONNODE_TYPES(V) \ VIDEO_NONNODE_TYPES(V) \ + NOTIFICATIONS_NONNODE_WRAPPER_TYPES(V) \ SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) \ WORKER_NONNODE_WRAPPER_TYPES(V) -#if ENABLE(XPATH) -#define DOM_OBJECT_XPATH_TYPES(V) \ - V(XPATHEVALUATOR, XPathEvaluator) \ - V(XPATHEXCEPTION, XPathException) \ - V(XPATHEXPRESSION, XPathExpression) \ - V(XPATHNSRESOLVER, XPathNSResolver) \ - V(XPATHRESULT, XPathResult) -#else -#define DOM_OBJECT_XPATH_TYPES(V) -#endif - -#if ENABLE(XSLT) -#define DOM_OBJECT_XSLT_TYPES(V) \ - V(XSLTPROCESSOR, XSLTProcessor) -#else -#define DOM_OBJECT_XSLT_TYPES(V) -#endif - #if ENABLE(DATABASE) #define DOM_OBJECT_DATABASE_TYPES(V) \ V(DATABASE, Database) \ @@ -438,16 +445,65 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #define DOM_OBJECT_WORKERS_TYPES(V) #endif -#if ENABLE(GEOLOCATION) +#if ENABLE(3D_CANVAS) +#define DOM_OBJECT_3D_CANVAS_TYPES(V) \ + V(WEBGLACTIVEINFO, WebGLActiveInfo) \ + V(WEBGLARRAY, WebGLArray) \ + V(WEBGLARRAYBUFFER, WebGLArrayBuffer) \ + V(WEBGLBUFFER, WebGLBuffer) \ + V(WEBGLBYTEARRAY, WebGLByteArray) \ + V(WEBGLFLOATARRAY, WebGLFloatArray) \ + V(WEBGLFRAMEBUFFER, WebGLFramebuffer) \ + V(WEBGLINTARRAY, WebGLIntArray) \ + V(WEBGLPROGRAM, WebGLProgram) \ + V(WEBGLRENDERBUFFER, WebGLRenderbuffer) \ + V(WEBGLRENDERINGCONTEXT, WebGLRenderingContext) \ + V(WEBGLSHADER, WebGLShader) \ + V(WEBGLSHORTARRAY, WebGLShortArray) \ + V(WEBGLTEXTURE, WebGLTexture) \ + V(WEBGLUNIFORMLOCATION, WebGLUniformLocation) \ + V(WEBGLUNSIGNEDBYTEARRAY, WebGLUnsignedByteArray) \ + V(WEBGLUNSIGNEDINTARRAY, WebGLUnsignedIntArray) \ + V(WEBGLUNSIGNEDSHORTARRAY, WebGLUnsignedShortArray) +#else +#define DOM_OBJECT_3D_CANVAS_TYPES(V) +#endif + +#if ENABLE(XPATH) +#define DOM_OBJECT_XPATH_TYPES(V) \ + V(XPATHEVALUATOR, XPathEvaluator) \ + V(XPATHEXCEPTION, XPathException) \ + V(XPATHEXPRESSION, XPathExpression) \ + V(XPATHNSRESOLVER, XPathNSResolver) \ + V(XPATHRESULT, XPathResult) +#else +#define DOM_OBJECT_XPATH_TYPES(V) +#endif + +#if ENABLE(XSLT) +#define DOM_OBJECT_XSLT_TYPES(V) \ + V(XSLTPROCESSOR, XSLTProcessor) +#else +#define DOM_OBJECT_XSLT_TYPES(V) +#endif + +#if ENABLE(INSPECTOR) +#define DOM_OBJECT_INSPECTOR_TYPES(V) \ + V(INSPECTORBACKEND, InspectorBackend) \ + V(INSPECTORFRONTENDHOST, InspectorFrontendHost) \ + V(INJECTEDSCRIPTHOST, InjectedScriptHost) +#else +#define DOM_OBJECT_INSPECTOR_TYPES(V) +#endif + #define DOM_OBJECT_GEOLOCATION_TYPES(V) \ V(COORDINATES, Coordinates) \ V(GEOLOCATION, Geolocation) \ V(GEOPOSITION, Geoposition) \ V(POSITIONERROR, PositionError) -#else -#define DOM_OBJECT_GEOLOCATION_TYPES(V) -#endif +#if PLATFORM(ANDROID) +// TODO: Upstream this guard. #if ENABLE(TOUCH_EVENTS) #define DOM_OBJECT_TOUCH_EVENT_TYPES(V) \ V(TOUCHLIST, TouchList) \ @@ -456,26 +512,30 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #else #define DOM_OBJECT_TOUCH_EVENT_TYPES(V) #endif +#endif -#if PLATFORM(CHROMIUM) +#if PLATFORM(ANDROID) +#define DOM_OBJECT_VOIDCALLBACK_TYPES(V) \ + V(VOIDCALLBACK, VoidCallback) +#else +#define DOM_OBJECT_VOIDCALLBACK_TYPES(V) +#endif + +#if PLATFORM(ANDROID) +// This block is modified, but is not Android-specific. #define DOM_OBJECT_TYPES(V) \ DOM_OBJECT_TYPES_1(V) \ DOM_OBJECT_TYPES_2(V) \ DOM_OBJECT_DATABASE_TYPES(V) \ DOM_OBJECT_STORAGE_TYPES(V) \ DOM_OBJECT_WORKERS_TYPES(V) \ + DOM_OBJECT_3D_CANVAS_TYPES(V) \ DOM_OBJECT_XPATH_TYPES(V) \ DOM_OBJECT_XSLT_TYPES(V) \ - V(INSPECTORBACKEND, InspectorBackend) -#elif PLATFORM(ANDROID) -#define DOM_OBJECT_TYPES(V) \ - DOM_OBJECT_TYPES_1(V) \ - DOM_OBJECT_TYPES_2(V) \ - DOM_OBJECT_DATABASE_TYPES(V) \ + DOM_OBJECT_INSPECTOR_TYPES(V) \ DOM_OBJECT_GEOLOCATION_TYPES(V) \ - DOM_OBJECT_STORAGE_TYPES(V) \ DOM_OBJECT_TOUCH_EVENT_TYPES(V) \ - DOM_OBJECT_WORKERS_TYPES(V) + DOM_OBJECT_VOIDCALLBACK_TYPES(V) #endif #if ENABLE(SVG) diff --git a/WebCore/bindings/v8/V8IsolatedWorld.cpp b/WebCore/bindings/v8/V8IsolatedWorld.cpp index 1457545..cb65097 100644 --- a/WebCore/bindings/v8/V8IsolatedWorld.cpp +++ b/WebCore/bindings/v8/V8IsolatedWorld.cpp @@ -43,34 +43,31 @@ namespace WebCore { -static int isolatedWorldCount = 0; +int V8IsolatedWorld::isolatedWorldCount = 0; -static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world) +void V8IsolatedWorld::contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world) { // Our context is going away. Time to clean up the world. V8IsolatedWorld* world = static_cast<V8IsolatedWorld*>(isolated_world); delete world; } -void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup) +V8IsolatedWorld::V8IsolatedWorld(V8Proxy* proxy, int extensionGroup) { + ++isolatedWorldCount; + v8::HandleScope scope; - v8::Persistent<v8::Context> context = proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup); + m_context = SharedPersistent<v8::Context>::create(proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup)); + if (m_context->get().IsEmpty()) + return; // Run code in the new context. - v8::Context::Scope context_scope(context); + v8::Context::Scope context_scope(m_context->get()); - // The lifetime of this object is controlled by the V8 GC. - // We need to create the world before touching DOM wrappers. - V8IsolatedWorld* world = new V8IsolatedWorld(context); + getGlobalObject(m_context->get())->SetPointerInInternalField(V8Custom::kDOMWindowEnteredIsolatedWorldIndex, this); - V8Proxy::installHiddenObjectPrototype(context); - proxy->installDOMWindow(context, proxy->frame()->domWindow()); - - proxy->frame()->loader()->client()->didCreateIsolatedScriptContext(); - - for (size_t i = 0; i < sources.size(); ++i) - proxy->evaluate(sources[i], 0); + V8Proxy::installHiddenObjectPrototype(m_context->get()); + proxy->installDOMWindow(m_context->get(), proxy->frame()->domWindow()); // Using the default security token means that the canAccess is always // called, which is slow. @@ -78,49 +75,20 @@ void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* // created contexts so that they can all be updated when the // document domain // changes. - // FIXME: Move this statement above proxy->evaluate? It seems like we - // should set up the token before running the script. - context->UseDefaultSecurityToken(); + m_context->get()->UseDefaultSecurityToken(); - context.Dispose(); - // WARNING! This might well delete |world|. + proxy->frame()->loader()->client()->didCreateIsolatedScriptContext(); } -V8IsolatedWorld::V8IsolatedWorld(v8::Handle<v8::Context> context) - : m_context(v8::Persistent<v8::Context>::New(context)) +void V8IsolatedWorld::destroy() { - ++isolatedWorldCount; - m_context.MakeWeak(this, &contextWeakReferenceCallback); - m_context->Global()->SetHiddenValue(V8HiddenPropertyName::isolatedWorld(), v8::External::Wrap(this)); + m_context->get().MakeWeak(this, &contextWeakReferenceCallback); } V8IsolatedWorld::~V8IsolatedWorld() { --isolatedWorldCount; - m_context.Dispose(); - m_context.Clear(); -} - -V8IsolatedWorld* V8IsolatedWorld::getEntered() -{ - if (isolatedWorldCount == 0) { - // This is a temporary performance optimization. Essentially, - // GetHiddenValue is too slow for this code path. We need to get the - // V8 team to add a real property to v8::Context for isolated worlds. - // Until then, we optimize the common case of not having any isolated - // worlds at all. - return 0; - } - - if (!v8::Context::InContext()) - return 0; - v8::HandleScope scope; - - v8::Local<v8::Value> world = v8::Context::GetEntered()->Global()->GetHiddenValue(V8HiddenPropertyName::isolatedWorld()); - if (world.IsEmpty()) - return 0; - - return static_cast<V8IsolatedWorld*>(v8::External::Unwrap(world)); + m_context->disposeHandle(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8IsolatedWorld.h b/WebCore/bindings/v8/V8IsolatedWorld.h index 2036e65..6313da8 100644 --- a/WebCore/bindings/v8/V8IsolatedWorld.h +++ b/WebCore/bindings/v8/V8IsolatedWorld.h @@ -35,6 +35,7 @@ #include "V8DOMMap.h" #include "V8Index.h" +#include "V8Proxy.h" #include "V8Utilities.h" #include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode @@ -57,11 +58,15 @@ namespace WebCore { // class V8IsolatedWorld { public: + // Creates an isolated world. To destroy it, call destroy(). + // This will delete the isolated world when the context it owns is GC'd. + V8IsolatedWorld(V8Proxy* proxy, int extensionGroup); ~V8IsolatedWorld(); - // Evaluate JavaScript in a new isolated world. The script has access - // to the DOM of the document associated with |proxy|. - static void evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup); + // Call this to destroy the isolated world. It will be deleted sometime + // after this call, once all script references to the world's context + // have been dropped. + void destroy(); // Returns the isolated world associated with // v8::Context::GetEntered(). Because worlds are isolated, the entire @@ -71,26 +76,45 @@ namespace WebCore { // FIXME: Consider edge cases with DOM mutation events that might // violate this invariant. // - static V8IsolatedWorld* getEntered(); + static V8IsolatedWorld* getEntered() + { + // This is a temporary performance optimization. Essentially, + // GetHiddenValue is too slow for this code path. We need to get the + // V8 team to add a real property to v8::Context for isolated worlds. + // Until then, we optimize the common case of not having any isolated + // worlds at all. + if (!isolatedWorldCount) + return 0; + if (!v8::Context::InContext()) + return 0; + return reinterpret_cast<V8IsolatedWorld*>(getGlobalObject(v8::Context::GetEntered())->GetPointerFromInternalField(V8Custom::kDOMWindowEnteredIsolatedWorldIndex)); + } - v8::Handle<v8::Context> context() { return m_context; } + v8::Handle<v8::Context> context() { return m_context->get(); } + PassRefPtr<SharedPersistent<v8::Context> > sharedContext() { return m_context; } DOMDataStore* getDOMDataStore() const { return m_domDataStore.getStore(); } private: - // The lifetime of an isolated world is managed by the V8 garbage - // collector. In particular, the object created by this constructor is - // freed when |context| is garbage collected. - explicit V8IsolatedWorld(v8::Handle<v8::Context> context); + static v8::Handle<v8::Object> getGlobalObject(v8::Handle<v8::Context> context) + { + return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); + } + + // Called by the garbage collector when our JavaScript context is about + // to be destroyed. + static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world); // The v8::Context for the isolated world. This object is keep on the // heap as long as |m_context| has not been garbage collected. - v8::Persistent<v8::Context> m_context; + RefPtr<SharedPersistent<v8::Context> > m_context; // The backing store for the isolated world's DOM wrappers. This class // doesn't have visibility into the wrappers. This handle simply helps // manage their lifetime. DOMDataStoreHandle m_domDataStore; + + static int isolatedWorldCount; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/V8LazyEventListener.cpp b/WebCore/bindings/v8/V8LazyEventListener.cpp index 59fa7be..16b21d6 100644 --- a/WebCore/bindings/v8/V8LazyEventListener.cpp +++ b/WebCore/bindings/v8/V8LazyEventListener.cpp @@ -33,199 +33,122 @@ #include "Frame.h" #include "V8Binding.h" +#include "V8HiddenPropertyName.h" #include "V8Proxy.h" +#include "WorldContextHandle.h" + +#include <wtf/StdLibExtras.h> namespace WebCore { -V8LazyEventListener::V8LazyEventListener(Frame *frame, const String& code, const String& functionName, bool isSVGEvent) - : V8AbstractEventListener(frame, true) - , m_code(code) +V8LazyEventListener::V8LazyEventListener(const String& functionName, bool isSVGEvent, const String& code, const String sourceURL, int lineNumber, int columnNumber, const WorldContextHandle& worldContext) + : V8AbstractEventListener(true, worldContext) , m_functionName(functionName) , m_isSVGEvent(isSVGEvent) - , m_compiled(false) - , m_wrappedFunctionCompiled(false) -{ -} - -V8LazyEventListener::~V8LazyEventListener() -{ - disposeListenerObject(); - - // Dispose wrapped function - if (!m_wrappedFunction.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_wrappedFunction); -#endif - m_wrappedFunction.Dispose(); - m_wrappedFunction.Clear(); - } -} - -v8::Local<v8::Function> V8LazyEventListener::getListenerFunction() + , m_code(code) + , m_sourceURL(sourceURL) + , m_lineNumber(lineNumber) + , m_columnNumber(columnNumber) { - if (m_compiled) { - ASSERT(m_listener.IsEmpty() || m_listener->IsFunction()); - return m_listener.IsEmpty() ? v8::Local<v8::Function>() : v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener)); - } - - m_compiled = true; - - ASSERT(m_frame); - - { - // Switch to the context of m_frame. - v8::HandleScope handleScope; - - // Use the outer scope to hold context. - v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); - // Bail out if we could not get the context. - if (v8Context.IsEmpty()) - return v8::Local<v8::Function>(); - - v8::Context::Scope scope(v8Context); - - // Wrap function around the event code. The parenthesis around the function are needed so that evaluating the code yields - // the function value. Without the parenthesis the function value is thrown away. - - // Make it an anonymous function to avoid name conflict for cases like - // <body onload='onload()'> - // <script> function onload() { alert('hi'); } </script>. - // Set function name to function object instead. - // See issue 944690. - // - // The ECMAScript spec says (very obliquely) that the parameter to an event handler is named "evt". - // - // Don't use new lines so that lines in the modified handler - // have the same numbers as in the original code. - String code = "(function (evt) {"; - code.append(m_code); - code.append("\n})"); - - v8::Handle<v8::String> codeExternalString = v8ExternalString(code); - v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_frame->document()->url(), m_lineNumber - 1); - if (!script.IsEmpty()) { - V8Proxy* proxy = V8Proxy::retrieve(m_frame); - ASSERT(proxy); - v8::Local<v8::Value> value = proxy->runScript(script, false); - if (!value.IsEmpty()) { - ASSERT(value->IsFunction()); - v8::Local<v8::Function> listenerFunction = v8::Local<v8::Function>::Cast(value); - listenerFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); - - m_listener = v8::Persistent<v8::Function>::New(listenerFunction); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener); -#endif - } - } - } - - ASSERT(m_listener.IsEmpty() || m_listener->IsFunction()); - return m_listener.IsEmpty() ? v8::Local<v8::Function>() : v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener)); } -v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event, bool isWindowEvent) +v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Function> handlerFunction = getWrappedListenerFunction(); - v8::Local<v8::Object> receiver = getReceiverObject(event, isWindowEvent); + v8::Local<v8::Function> handlerFunction = v8::Local<v8::Function>::Cast(getListenerObject(context)); + v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); v8::Handle<v8::Value> parameters[1] = { jsEvent }; - V8Proxy* proxy = V8Proxy::retrieve(m_frame); - return proxy->callFunction(handlerFunction, receiver, 1, parameters); -} + if (V8Proxy* proxy = V8Proxy::retrieve(context)) + return proxy->callFunction(handlerFunction, receiver, 1, parameters); + return v8::Local<v8::Value>(); +} static v8::Handle<v8::Value> V8LazyEventListenerToString(const v8::Arguments& args) { - return args.Callee()->GetHiddenValue(v8::String::New("toStringString")); + return args.Holder()->GetHiddenValue(V8HiddenPropertyName::toStringString()); } - -v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction() +void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context) { - if (m_wrappedFunctionCompiled) { - ASSERT(m_wrappedFunction.IsEmpty() || m_wrappedFunction->IsFunction()); - return m_wrappedFunction.IsEmpty() ? v8::Local<v8::Function>() : v8::Local<v8::Function>::New(m_wrappedFunction); - } - - m_wrappedFunctionCompiled = true; - - { - // Switch to the context of m_frame. - v8::HandleScope handleScope; - - // Use the outer scope to hold context. - v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); - // Bail out if we cannot get the context. - if (v8Context.IsEmpty()) - return v8::Local<v8::Function>(); - - v8::Context::Scope scope(v8Context); - - // FIXME: cache the wrapper function. - - // Nodes other than the document object, when executing inline event handlers push document, form, and the target node on the scope chain. - // We do this by using 'with' statement. - // See chrome/fast/forms/form-action.html - // chrome/fast/forms/selected-index-value.html - // base/fast/overflow/onscroll-layer-self-destruct.html - // - // Don't use new lines so that lines in the modified handler - // have the same numbers as in the original code. - String code = "(function (evt) {" \ - "with (this.ownerDocument ? this.ownerDocument : {}) {" \ - "with (this.form ? this.form : {}) {" \ - "with (this) {" \ - "return (function(evt){"; - code.append(m_code); - // Insert '\n' otherwise //-style comments could break the handler. - code.append( "\n}).call(this, evt);}}}})"); - v8::Handle<v8::String> codeExternalString = v8ExternalString(code); - v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_frame->document()->url(), m_lineNumber); - if (!script.IsEmpty()) { - V8Proxy* proxy = V8Proxy::retrieve(m_frame); - ASSERT(proxy); - v8::Local<v8::Value> value = proxy->runScript(script, false); - if (!value.IsEmpty()) { - ASSERT(value->IsFunction()); - - m_wrappedFunction = v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(value)); - - // Change the toString function on the wrapper function to avoid it returning the source for the actual wrapper function. Instead - // it returns source for a clean wrapper function with the event argument wrapping the event source code. The reason for this - // is that some web sites uses toString on event functions and the evals the source returned (some times a RegExp is applied as - // well) for some other use. That fails miserably if the actual wrapper source is returned. - v8::Local<v8::FunctionTemplate> toStringTemplate = v8::FunctionTemplate::New(V8LazyEventListenerToString); - v8::Local<v8::Function> toStringFunction; - if (!toStringTemplate.IsEmpty()) - toStringFunction = toStringTemplate->GetFunction(); - if (!toStringFunction.IsEmpty()) { - String toStringResult = "function "; - toStringResult.append(m_functionName); - toStringResult.append("("); - if (m_isSVGEvent) - toStringResult.append("evt"); - else - toStringResult.append("event"); - toStringResult.append(") {\n "); - toStringResult.append(m_code); - toStringResult.append("\n}"); - toStringFunction->SetHiddenValue(v8::String::New("toStringString"), v8ExternalString(toStringResult)); - m_wrappedFunction->Set(v8::String::New("toString"), toStringFunction); - } - -#ifndef NDEBUG - V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_wrappedFunction); -#endif - m_wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); + if (hasExistingListenerObject()) + return; + + v8::HandleScope handleScope; + + V8Proxy* proxy = V8Proxy::retrieve(context); + if (!proxy) + return; + + // Use the outer scope to hold context. + v8::Local<v8::Context> v8Context = worldContext().adjustedContext(proxy); + // Bail out if we cannot get the context. + if (v8Context.IsEmpty()) + return; + + v8::Context::Scope scope(v8Context); + + // FIXME: cache the wrapper function. + + // Nodes other than the document object, when executing inline event handlers push document, form, and the target node on the scope chain. + // We do this by using 'with' statement. + // See chrome/fast/forms/form-action.html + // chrome/fast/forms/selected-index-value.html + // base/fast/overflow/onscroll-layer-self-destruct.html + // + // Don't use new lines so that lines in the modified handler + // have the same numbers as in the original code. + String code = "(function (evt) {" \ + "with (this.ownerDocument ? this.ownerDocument : {}) {" \ + "with (this.form ? this.form : {}) {" \ + "with (this) {" \ + "return (function(evt){"; + code.append(m_code); + // Insert '\n' otherwise //-style comments could break the handler. + code.append( "\n}).call(this, evt);}}}})"); + v8::Handle<v8::String> codeExternalString = v8ExternalString(code); + v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_sourceURL, m_lineNumber); + if (!script.IsEmpty()) { + v8::Local<v8::Value> value = proxy->runScript(script, false); + if (!value.IsEmpty()) { + ASSERT(value->IsFunction()); + + v8::Local<v8::Function> wrappedFunction = v8::Local<v8::Function>::Cast(value); + + // Change the toString function on the wrapper function to avoid it + // returning the source for the actual wrapper function. Instead it + // returns source for a clean wrapper function with the event + // argument wrapping the event source code. The reason for this is + // that some web sites use toString on event functions and eval the + // source returned (sometimes a RegExp is applied as well) for some + // other use. That fails miserably if the actual wrapper source is + // returned. + DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ()); + if (toStringTemplate.IsEmpty()) + toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8LazyEventListenerToString)); + v8::Local<v8::Function> toStringFunction; + if (!toStringTemplate.IsEmpty()) + toStringFunction = toStringTemplate->GetFunction(); + if (!toStringFunction.IsEmpty()) { + String toStringResult = "function "; + toStringResult.append(m_functionName); + toStringResult.append("("); + toStringResult.append(m_isSVGEvent ? "evt" : "event"); + toStringResult.append(") {\n "); + toStringResult.append(m_code); + toStringResult.append("\n}"); + wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(), v8ExternalString(toStringResult)); + wrappedFunction->Set(v8::String::New("toString"), toStringFunction); } + + wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); + + setListenerObject(wrappedFunction); } } - - return v8::Local<v8::Function>::New(m_wrappedFunction); } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8LazyEventListener.h b/WebCore/bindings/v8/V8LazyEventListener.h index 62d9342..078dcf1 100644 --- a/WebCore/bindings/v8/V8LazyEventListener.h +++ b/WebCore/bindings/v8/V8LazyEventListener.h @@ -45,35 +45,27 @@ namespace WebCore { // A V8LazyEventListener is always a HTML event handler. class V8LazyEventListener : public V8AbstractEventListener { public: - static PassRefPtr<V8LazyEventListener> create(Frame* frame, const String& code, const String& functionName, bool isSVGEvent) + static PassRefPtr<V8LazyEventListener> create(const String& functionName, bool isSVGEvent, const String& code, const String& sourceURL, int lineNumber, int columnNumber, const WorldContextHandle& worldContext) { - return adoptRef(new V8LazyEventListener(frame, code, functionName, isSVGEvent)); + return adoptRef(new V8LazyEventListener(functionName, isSVGEvent, code, sourceURL, lineNumber, columnNumber, worldContext)); } - // For lazy event listener, the listener object is the same as its listener - // function without additional scope chains. - virtual v8::Local<v8::Object> getListenerObject() { return getWrappedListenerFunction(); } + virtual bool isLazy() const { return true; } + + protected: + virtual void prepareListenerObject(ScriptExecutionContext*); private: - V8LazyEventListener(Frame*, const String& code, const String& functionName, bool isSVGEvent); - virtual ~V8LazyEventListener(); + V8LazyEventListener(const String& functionName, bool isSVGEvent, const String& code, const String sourceURL, int lineNumber, int columnNumber, const WorldContextHandle& worldContext); - virtual bool virtualisAttribute() const { return true; } + virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); - String m_code; String m_functionName; bool m_isSVGEvent; - bool m_compiled; - - // If the event listener is on a non-document dom node, we compile the function with some implicit scope chains before it. - bool m_wrappedFunctionCompiled; - v8::Persistent<v8::Function> m_wrappedFunction; - - v8::Local<v8::Function> getWrappedListenerFunction(); - - virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*, bool isWindowEvent); - - v8::Local<v8::Function> getListenerFunction(); + String m_code; + String m_sourceURL; + int m_lineNumber; + int m_columnNumber; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/V8NPObject.cpp b/WebCore/bindings/v8/V8NPObject.cpp index b6bf0f7..bab3688 100644 --- a/WebCore/bindings/v8/V8NPObject.cpp +++ b/WebCore/bindings/v8/V8NPObject.cpp @@ -33,6 +33,7 @@ #include "V8NPObject.h" #include "HTMLPlugInElement.h" +#include "IdentifierRep.h" #include "NPV8Object.h" #include "V8CustomBinding.h" #include "V8DOMMap.h" @@ -44,7 +45,7 @@ #include "V8Proxy.h" #include "npruntime_impl.h" #include "npruntime_priv.h" -#include "wtf/OwnArrayPtr.h" +#include <wtf/OwnArrayPtr.h> using namespace WebCore; @@ -93,27 +94,31 @@ static v8::Handle<v8::Value> npObjectInvokeImpl(const v8::Arguments& args, Invok NPVariant result; VOID_TO_NPVARIANT(result); + bool retval = true; switch (functionId) { case InvokeMethod: if (npObject->_class->invoke) { v8::Handle<v8::String> functionName(v8::String::Cast(*args.Data())); NPIdentifier identifier = getStringIdentifier(functionName); - npObject->_class->invoke(npObject, identifier, npArgs.get(), numArgs, &result); + retval = npObject->_class->invoke(npObject, identifier, npArgs.get(), numArgs, &result); } break; case InvokeConstruct: if (npObject->_class->construct) - npObject->_class->construct(npObject, npArgs.get(), numArgs, &result); + retval = npObject->_class->construct(npObject, npArgs.get(), numArgs, &result); break; case InvokeDefault: if (npObject->_class->invokeDefault) - npObject->_class->invokeDefault(npObject, npArgs.get(), numArgs, &result); + retval = npObject->_class->invokeDefault(npObject, npArgs.get(), numArgs, &result); break; default: break; } - for (int i=0; i < numArgs; i++) + if (!retval) + throwError("Error calling method on NPObject!", V8Proxy::GeneralError); + + for (int i = 0; i < numArgs; i++) _NPN_ReleaseVariantValue(&npArgs[i]); // Unwrap return values. @@ -134,8 +139,8 @@ v8::Handle<v8::Value> npObjectInvokeDefaultHandler(const v8::Arguments& args) { if (args.IsConstructCall()) return npObjectInvokeImpl(args, InvokeConstruct); - else - return npObjectInvokeImpl(args, InvokeDefault); + + return npObjectInvokeImpl(args, InvokeDefault); } @@ -176,7 +181,9 @@ static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPI _NPN_ReleaseVariantValue(&result); return returnValue; - } else if (key->IsString() && npObject->_class->hasMethod && npObject->_class->hasMethod(npObject, identifier)) { + } + + if (key->IsString() && npObject->_class->hasMethod && npObject->_class->hasMethod(npObject, identifier)) { PrivateIdentifier* id = static_cast<PrivateIdentifier*>(identifier); v8::Persistent<v8::FunctionTemplate> functionTemplate = staticTemplateMap.get(id); // Cache templates using identifier as the key. @@ -271,6 +278,44 @@ v8::Handle<v8::Value> npObjectSetIndexedProperty(v8::Local<v8::Object> self, uin return npObjectSetProperty(self, identifier, value); } +v8::Handle<v8::Array> npObjectPropertyEnumerator(const v8::AccessorInfo& info, bool namedProperty) +{ + NPObject* npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, info.Holder()); + + // Verify that our wrapper wasn't using a NPObject which + // has already been deleted. + if (!npObject || !_NPN_IsAlive(npObject)) + throwError("NPObject deleted", V8Proxy::ReferenceError); + + if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate) { + uint32_t count; + NPIdentifier* identifiers; + if (npObject->_class->enumerate(npObject, &identifiers, &count)) { + v8::Handle<v8::Array> properties = v8::Array::New(count); + for (uint32_t i = 0; i < count; ++i) { + IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]); + if (namedProperty) + properties->Set(v8::Integer::New(i), v8::String::New(identifier->string())); + else + properties->Set(v8::Integer::New(i), v8::Integer::New(identifier->number())); + } + + return properties; + } + } + + return v8::Handle<v8::Array>(); +} + +v8::Handle<v8::Array> npObjectNamedPropertyEnumerator(const v8::AccessorInfo& info) +{ + return npObjectPropertyEnumerator(info, true); +} + +v8::Handle<v8::Array> npObjectIndexedPropertyEnumerator(const v8::AccessorInfo& info) +{ + return npObjectPropertyEnumerator(info, false); +} static void weakNPObjectCallback(v8::Persistent<v8::Value>, void* parameter); @@ -313,8 +358,8 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root if (npObjectDesc.IsEmpty()) { npObjectDesc = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); npObjectDesc->InstanceTemplate()->SetInternalFieldCount(V8Custom::kNPObjectInternalFieldCount); - npObjectDesc->InstanceTemplate()->SetNamedPropertyHandler(npObjectNamedPropertyGetter, npObjectNamedPropertySetter); - npObjectDesc->InstanceTemplate()->SetIndexedPropertyHandler(npObjectIndexedPropertyGetter, npObjectIndexedPropertySetter); + npObjectDesc->InstanceTemplate()->SetNamedPropertyHandler(npObjectNamedPropertyGetter, npObjectNamedPropertySetter, 0, 0, npObjectNamedPropertyEnumerator); + npObjectDesc->InstanceTemplate()->SetIndexedPropertyHandler(npObjectIndexedPropertyGetter, npObjectIndexedPropertySetter, 0, 0, npObjectIndexedPropertyEnumerator); npObjectDesc->InstanceTemplate()->SetCallAsFunctionHandler(npObjectInvokeDefaultHandler); } diff --git a/WebCore/bindings/v8/V8ObjectEventListener.cpp b/WebCore/bindings/v8/V8ObjectEventListener.cpp deleted file mode 100644 index f10766c..0000000 --- a/WebCore/bindings/v8/V8ObjectEventListener.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8ObjectEventListener.h" - -#include "Frame.h" -#include "V8Proxy.h" - -namespace WebCore { - -static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* parameter) -{ - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(parameter); - - // Remove the wrapper - Frame* frame = listener->frame(); - if (frame) { - V8Proxy* proxy = V8Proxy::retrieve(frame); - if (proxy) - proxy->objectListeners()->remove(listener); - - // Because the listener is no longer in the list, it must be disconnected from the frame to avoid dangling frame pointer - // in the destructor. - listener->disconnectFrame(); - } - listener->disposeListenerObject(); -} - -// An object event listener wrapper only holds a weak reference to the -// JS function. A strong reference can create a cycle. -// -// The lifetime of these objects is bounded by the life time of the JS -// wrapper of XHR or Node. So we can create a hidden reference from -// the JS wrapper to to its JS function. -// -// (map) -// XHR or Node <---------- JS_wrapper -// | (hidden) : ^ -// V V : (may be reachable by closure) -// V8_listener --------> JS_function -// (weak) <-- may create a cycle if it is strong -// -// The persistent reference is made weak in the constructor of -// V8ObjectEventListener. - -V8ObjectEventListener::V8ObjectEventListener(Frame* frame, v8::Local<v8::Object> listener, bool isInline) - : V8EventListener(frame, listener, isInline) -{ - m_listener.MakeWeak(this, weakObjectEventListenerCallback); -} - -V8ObjectEventListener::~V8ObjectEventListener() -{ - if (m_frame) { - ASSERT(!m_listener.IsEmpty()); - V8Proxy* proxy = V8Proxy::retrieve(m_frame); - if (proxy) - proxy->objectListeners()->remove(this); - } - - disposeListenerObject(); -} - -} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp index 1cfafb8..5da73d5 100644 --- a/WebCore/bindings/v8/V8Proxy.cpp +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -32,11 +32,15 @@ #include "V8Proxy.h" #include "CSSMutableStyleDeclaration.h" -#include "CString.h" +#include "DateExtension.h" #include "DOMObjectsInclude.h" #include "DocumentLoader.h" #include "FrameLoaderClient.h" +#include "InspectorTimelineAgent.h" +#include "Page.h" +#include "PageGroup.h" #include "ScriptController.h" +#include "StorageNamespace.h" #include "V8Binding.h" #include "V8Collection.h" #include "V8ConsoleMessage.h" @@ -46,12 +50,17 @@ #include "V8HiddenPropertyName.h" #include "V8Index.h" #include "V8IsolatedWorld.h" +#include "WorkerContextExecutionProxy.h" +#include <algorithm> +#include <stdio.h> +#include <utility> #include <v8.h> #include <v8-debug.h> #include <wtf/Assertions.h> #include <wtf/OwnArrayPtr.h> #include <wtf/StdLibExtras.h> +#include <wtf/StringExtras.h> #include <wtf/UnusedParam.h> #if PLATFORM(CHROMIUM) @@ -62,30 +71,45 @@ #include "TimeCounter.h" #endif +#if PLATFORM(ANDROID) +#include "CString.h" +#endif + namespace WebCore { v8::Persistent<v8::Context> V8Proxy::m_utilityContext; // Static list of registered extensions -V8ExtensionList V8Proxy::m_extensions; +V8Extensions V8Proxy::m_extensions; -const char* V8Proxy::kContextDebugDataType = "type"; -const char* V8Proxy::kContextDebugDataValue = "value"; +void batchConfigureAttributes(v8::Handle<v8::ObjectTemplate> instance, + v8::Handle<v8::ObjectTemplate> proto, + const BatchedAttribute* attributes, + size_t attributeCount) +{ + for (size_t i = 0; i < attributeCount; ++i) + configureAttribute(instance, proto, attributes[i]); +} -void batchConfigureAttributes(v8::Handle<v8::ObjectTemplate> instance, v8::Handle<v8::ObjectTemplate> proto, const BatchedAttribute* attributes, size_t attributeCount) +void batchConfigureCallbacks(v8::Handle<v8::ObjectTemplate> proto, + v8::Handle<v8::Signature> signature, + v8::PropertyAttribute attributes, + const BatchedCallback* callbacks, + size_t callbackCount) { - for (size_t i = 0; i < attributeCount; ++i) { - const BatchedAttribute* attribute = &attributes[i]; - (attribute->onProto ? proto : instance)->SetAccessor(v8::String::New(attribute->name), - attribute->getter, - attribute->setter, - attribute->data == V8ClassIndex::INVALID_CLASS_INDEX ? v8::Handle<v8::Value>() : v8::Integer::New(V8ClassIndex::ToInt(attribute->data)), - attribute->settings, - attribute->attribute); + for (size_t i = 0; i < callbackCount; ++i) { + proto->Set(v8::String::New(callbacks[i].name), + v8::FunctionTemplate::New(callbacks[i].callback, + v8::Handle<v8::Value>(), + signature), + attributes); } } -void batchConfigureConstants(v8::Handle<v8::FunctionTemplate> functionDescriptor, v8::Handle<v8::ObjectTemplate> proto, const BatchedConstant* constants, size_t constantCount) +void batchConfigureConstants(v8::Handle<v8::FunctionTemplate> functionDescriptor, + v8::Handle<v8::ObjectTemplate> proto, + const BatchedConstant* constants, + size_t constantCount) { for (size_t i = 0; i < constantCount; ++i) { const BatchedConstant* constant = &constants[i]; @@ -213,6 +237,14 @@ static void reportFatalErrorInV8(const char* location, const char* message) handleFatalErrorInV8(); } +V8Proxy::V8Proxy(Frame* frame) + : m_frame(frame) + , m_inlineCode(false) + , m_timerCallback(false) + , m_recursion(0) +{ +} + V8Proxy::~V8Proxy() { clearForClose(); @@ -230,22 +262,6 @@ void V8Proxy::destroyGlobal() } } -static void disconnectEventListenersInList(V8EventListenerList& list) -{ - V8EventListenerList::iterator it = list.begin(); - while (it != list.end()) { - (*it)->disconnectFrame(); - ++it; - } - list.clear(); -} - -void V8Proxy::disconnectEventListeners() -{ - disconnectEventListenersInList(m_eventListeners); - disconnectEventListenersInList(m_objectListeners); -} - v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine) #ifdef ANDROID_INSTRUMENT { @@ -288,6 +304,7 @@ bool V8Proxy::handleOutOfMemory() // TODO (andreip): ChromeBridge -> BrowserBridge? ChromiumBridge::notifyJSOutOfMemory(frame); #endif + // Disable JS. Settings* settings = frame->settings(); ASSERT(settings); @@ -296,10 +313,48 @@ bool V8Proxy::handleOutOfMemory() return true; } -void V8Proxy::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup) +void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup) { initContextIfNeeded(); - V8IsolatedWorld::evaluate(sources, this, extensionGroup); + + v8::HandleScope handleScope; + V8IsolatedWorld* world = 0; + + if (worldID > 0) { + IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(worldID); + if (iter != m_isolatedWorlds.end()) { + world = iter->second; + } else { + world = new V8IsolatedWorld(this, extensionGroup); + if (world->context().IsEmpty()) { + delete world; + return; + } + + m_isolatedWorlds.set(worldID, world); + + // Setup context id for JS debugger. + if (!setInjectedScriptContextDebugId(world->context())) { + m_isolatedWorlds.take(worldID); + delete world; + return; + } + } + } else { + world = new V8IsolatedWorld(this, extensionGroup); + if (world->context().IsEmpty()) { + delete world; + return; + } + } + + v8::Local<v8::Context> context = v8::Local<v8::Context>::New(world->context()); + v8::Context::Scope context_scope(context); + for (size_t i = 0; i < sources.size(); ++i) + evaluate(sources[i], 0); + + if (worldID == 0) + world->destroy(); } void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) @@ -316,17 +371,16 @@ void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int ASSERT(V8DOMWrapper::convertDOMWrapperToNative<DOMWindow>(windowWrapper) == m_frame->domWindow()); v8::Persistent<v8::Context> context = createNewContext(v8::Handle<v8::Object>(), extensionGroup); + if (context.IsEmpty()) + return; + v8::Context::Scope contextScope(context); // Setup context id for JS debugger. - v8::Handle<v8::Object> contextData = v8::Object::New(); - v8::Handle<v8::Value> windowContextData = windowContext->GetData(); - if (windowContextData->IsObject()) { - v8::Handle<v8::String> propertyName = v8::String::New(kContextDebugDataValue); - contextData->Set(propertyName, v8::Object::Cast(*windowContextData)->Get(propertyName)); + if (!setInjectedScriptContextDebugId(context)) { + context.Dispose(); + return; } - contextData->Set(v8::String::New(kContextDebugDataType), v8::String::New("injected")); - context->SetData(contextData); v8::Handle<v8::Object> global = context->Global(); @@ -352,41 +406,73 @@ void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int context.Dispose(); } +bool V8Proxy::setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContext) +{ + // Setup context id for JS debugger. + v8::Context::Scope contextScope(targetContext); + if (m_context.IsEmpty()) + return false; + int debugId = contextDebugId(m_context); + + char buffer[32]; + if (debugId == -1) + snprintf(buffer, sizeof(buffer), "injected"); + else + snprintf(buffer, sizeof(buffer), "injected,%d", debugId); + targetContext->SetData(v8::String::New(buffer)); + + return true; +} + v8::Local<v8::Value> V8Proxy::evaluate(const ScriptSourceCode& source, Node* node) { ASSERT(v8::Context::InContext()); - LOCK_V8; - // Compile the script. - v8::Local<v8::String> code = v8ExternalString(source.source()); -#if PLATFORM(CHROMIUM) - // TODO(andreip): ChromeBridge->BrowserBridge? - ChromiumBridge::traceEventBegin("v8.compile", node, ""); -#endif + V8GCController::checkMemoryUsage(); - // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at - // 1, whereas v8 starts at 0. - v8::Handle<v8::Script> script = compileScript(code, source.url(), source.startLine() - 1); -#if PLATFORM(CHROMIUM) - // TODO(andreip): ChromeBridge->BrowserBridge? - ChromiumBridge::traceEventEnd("v8.compile", node, ""); - ChromiumBridge::traceEventBegin("v8.run", node, ""); +#if ENABLE(INSPECTOR) + if (InspectorTimelineAgent* timelineAgent = m_frame->page() ? m_frame->page()->inspectorTimelineAgent() : 0) + timelineAgent->willEvaluateScript(source.url().isNull() ? String() : source.url().string(), source.startLine()); #endif + v8::Local<v8::Value> result; { - // Isolate exceptions that occur when executing the code. These - // exceptions should not interfere with javascript code we might - // evaluate from C++ when returning from here. + // Isolate exceptions that occur when compiling and executing + // the code. These exceptions should not interfere with + // javascript code we might evaluate from C++ when returning + // from here. v8::TryCatch tryCatch; tryCatch.SetVerbose(true); + // Compile the script. + v8::Local<v8::String> code = v8ExternalString(source.source()); +#if PLATFORM(CHROMIUM) + // TODO(andreip): ChromeBridge->BrowserBridge? + ChromiumBridge::traceEventBegin("v8.compile", node, ""); +#endif + + // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at + // 1, whereas v8 starts at 0. + v8::Handle<v8::Script> script = compileScript(code, source.url(), source.startLine() - 1); +#if PLATFORM(CHROMIUM) + // TODO(andreip): ChromeBridge->BrowserBridge? + ChromiumBridge::traceEventEnd("v8.compile", node, ""); + + ChromiumBridge::traceEventBegin("v8.run", node, ""); +#endif // Set inlineCode to true for <a href="javascript:doSomething()"> // and false for <script>doSomething</script>. We make a rough guess at // this based on whether the script source has a URL. result = runScript(script, source.url().string().isNull()); } + +#if ENABLE(INSPECTOR) + if (InspectorTimelineAgent* timelineAgent = m_frame->page() ? m_frame->page()->inspectorTimelineAgent() : 0) + timelineAgent->didEvaluateScript(); +#endif + #if PLATFORM(CHROMIUM) - // TODO(andreip): ChromeBridge->BrowserBridge? + // TODO(andreip): upstream CHROMIUM guards to webkit.org ChromiumBridge::traceEventEnd("v8.run", node, ""); #endif return result; @@ -407,6 +493,7 @@ v8::Local<v8::Value> V8Proxy::runScriptInternal(v8::Handle<v8::Script> script, b if (script.IsEmpty()) return notHandledByInterceptor(); + V8GCController::checkMemoryUsage(); // Compute the source string and prevent against infinite recursion. if (m_recursion >= kMaxRecursionDepth) { v8::Local<v8::String> code = v8ExternalString("throw RangeError('Recursion too deep')"); @@ -431,15 +518,18 @@ v8::Local<v8::Value> V8Proxy::runScriptInternal(v8::Handle<v8::Script> script, b v8::Local<v8::Value> result; { V8ConsoleMessage::Scope scope; - m_recursion++; // See comment in V8Proxy::callFunction. m_frame->keepAlive(); + m_recursion++; result = script->Run(); m_recursion--; } + // Release the storage mutex if applicable. + releaseStorageMutex(); + if (handleOutOfMemory()) ASSERT(result.IsEmpty()); @@ -461,14 +551,22 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::JavaScriptExecuteTimeCounter); #endif - - // For now, we don't put any artificial limitations on the depth - // of recursion that stems from calling functions. This is in - // contrast to the script evaluations. + V8GCController::checkMemoryUsage(); v8::Local<v8::Value> result; { V8ConsoleMessage::Scope scope; + if (m_recursion >= kMaxRecursionDepth) { + v8::Local<v8::String> code = v8::String::New("throw new RangeError('Maximum call stack size exceeded.')"); + if (code.IsEmpty()) + return result; + v8::Local<v8::Script> script = v8::Script::Compile(code); + if (script.IsEmpty()) + return result; + script->Run(); + return result; + } + // Evaluating the JavaScript could cause the frame to be deallocated, // so we start the keep alive timer here. // Frame::keepAlive method adds the ref count of the frame and sets a @@ -476,9 +574,14 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 // execution finishs before firing the timer. m_frame->keepAlive(); + m_recursion++; result = function->Call(receiver, argc, args); + m_recursion--; } + // Release the storage mutex if applicable. + releaseStorageMutex(); + if (v8::V8::IsDead()) handleFatalErrorInV8(); @@ -508,14 +611,10 @@ v8::Local<v8::Value> V8Proxy::newInstance(v8::Handle<v8::Function> constructor, return result; } -v8::Local<v8::Object> V8Proxy::createWrapperFromCache(V8ClassIndex::V8WrapperType type) +v8::Local<v8::Object> V8Proxy::createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType type) { - int classIndex = V8ClassIndex::ToInt(type); - v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex)); - if (!clone.IsEmpty()) - return clone; - // Not in cache. + int classIndex = V8ClassIndex::ToInt(type); initContextIfNeeded(); v8::Context::Scope scope(m_context); v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(m_context)); @@ -547,7 +646,14 @@ DOMWindow* V8Proxy::retrieveWindow(v8::Handle<v8::Context> context) Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context) { - return retrieveWindow(context)->frame(); + DOMWindow* window = retrieveWindow(context); + Frame* frame = window->frame(); + if (frame && frame->domWindow() == window) + return frame; + // We return 0 here because |context| is detached from the Frame. If we + // did return |frame| we could get in trouble because the frame could be + // navigated to another security origin. + return 0; } Frame* V8Proxy::retrieveFrameForEnteredContext() @@ -597,60 +703,6 @@ V8Proxy* V8Proxy::retrieve(ScriptExecutionContext* context) void V8Proxy::disconnectFrame() { - disconnectEventListeners(); -} - -bool V8Proxy::isEnabled() -{ - Settings* settings = m_frame->settings(); - if (!settings) - return false; - - // In the common case, JavaScript is enabled and we're done. - if (settings->isJavaScriptEnabled()) - return true; - - // If JavaScript has been disabled, we need to look at the frame to tell - // whether this script came from the web or the embedder. Scripts from the - // embedder are safe to run, but scripts from the other sources are - // disallowed. - Document* document = m_frame->document(); - if (!document) - return false; - - SecurityOrigin* origin = document->securityOrigin(); - if (origin->protocol().isEmpty()) - return false; // Uninitialized document - - if (origin->protocol() == "http" || origin->protocol() == "https") - return false; // Web site - - // FIXME: the following are application decisions, and they should - // not be made at this layer. instead, we should bridge out to the - // embedder to allow them to override policy here. - -#if PLATFORM(CHROMIUM) - // TODO(andreip): ChromeBridge->BrowserBridge? - if (origin->protocol() == ChromiumBridge::uiResourceProtocol()) - return true; // Embedder's scripts are ok to run -#endif - - // If the scheme is ftp: or file:, an empty file name indicates a directory - // listing, which requires JavaScript to function properly. - const char* kDirProtocols[] = { "ftp", "file" }; -#if PLATFORM(ANDROID) - // TODO(andreip): Port arraysize function to Android. There's one in Gears. - for (size_t i = 0; i < 2; ++i) { -#else - for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { -#endif - if (origin->protocol() == kDirProtocols[i]) { - const KURL& url = document->url(); - return url.pathAfterLastSlash() == url.pathEnd(); - } - } - - return false; // Other protocols fall through to here } void V8Proxy::updateDocumentWrapper(v8::Handle<v8::Value> wrapper) @@ -677,9 +729,8 @@ void V8Proxy::clearDocumentWrapper() void V8Proxy::updateDocumentWrapperCache() { - LOCK_V8; v8::HandleScope handleScope; - v8::Context::Scope contextScope(context()); + v8::Context::Scope contextScope(m_context); // If the document has no frame, NodeToV8Object might get the // document wrapper for a document that is about to be deleted. @@ -727,10 +778,34 @@ void V8Proxy::disposeContextHandles() } } +void V8Proxy::releaseStorageMutex() +{ + // If we've just left a top level script context and local storage has been + // instantiated, we must ensure that any storage locks have been freed. + // Per http://dev.w3.org/html5/spec/Overview.html#storage-mutex + if (m_recursion != 0) + return; + Page* page = m_frame->page(); + if (!page) + return; + if (page->group().hasLocalStorage()) + page->group().localStorage()->unlock(); +} + +void V8Proxy::resetIsolatedWorlds() +{ + for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); + iter != m_isolatedWorlds.end(); ++iter) { + iter->second->destroy(); + } + m_isolatedWorlds.clear(); +} + void V8Proxy::clearForClose() { + resetIsolatedWorlds(); + if (!m_context.IsEmpty()) { - LOCK_V8; v8::HandleScope handleScope; clearDocumentWrapper(); @@ -740,10 +815,9 @@ void V8Proxy::clearForClose() void V8Proxy::clearForNavigation() { - disconnectEventListeners(); + resetIsolatedWorlds(); if (!m_context.IsEmpty()) { - LOCK_V8; v8::HandleScope handle; clearDocumentWrapper(); @@ -816,6 +890,10 @@ void V8Proxy::updateDocument() // global object wrapper succeed. initContextIfNeeded(); + // Bail out if context initialization failed. + if (m_context.IsEmpty()) + return; + // We have a new document and we need to update the cache. updateDocumentWrapperCache(); @@ -824,7 +902,6 @@ void V8Proxy::updateDocument() void V8Proxy::updateSecurityOrigin() { - LOCK_V8; v8::HandleScope scope; setSecurityToken(); } @@ -861,14 +938,20 @@ bool V8Proxy::canAccessPrivate(DOMWindow* targetWindow) String message; - DOMWindow* originWindow = retrieveWindow(currentContext()); - if (originWindow == targetWindow) + v8::Local<v8::Context> activeContext = v8::Context::GetCalling(); + if (activeContext.IsEmpty()) { + // There is a single activation record on the stack, so that must + // be the activeContext. + activeContext = v8::Context::GetCurrent(); + } + DOMWindow* activeWindow = retrieveWindow(activeContext); + if (activeWindow == targetWindow) return true; - if (!originWindow) + if (!activeWindow) return false; - const SecurityOrigin* activeSecurityOrigin = originWindow->securityOrigin(); + const SecurityOrigin* activeSecurityOrigin = activeWindow->securityOrigin(); const SecurityOrigin* targetSecurityOrigin = targetWindow->securityOrigin(); // We have seen crashes were the security origin of the target has not been @@ -881,7 +964,7 @@ bool V8Proxy::canAccessPrivate(DOMWindow* targetWindow) // Allow access to a "about:blank" page if the dynamic context is a // detached context of the same frame as the blank page. - if (targetSecurityOrigin->isEmpty() && originWindow->frame() == targetWindow->frame()) + if (targetSecurityOrigin->isEmpty() && activeWindow->frame() == targetWindow->frame()) return true; return false; @@ -930,21 +1013,26 @@ v8::Persistent<v8::Context> V8Proxy::createNewContext(v8::Handle<v8::Object> glo // Install a security handler with V8. globalTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW)); + globalTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount); + + // Used to avoid sleep calls in unload handlers. + if (!registeredExtensionWithV8(DateExtension::get())) + registerExtension(DateExtension::get(), String()); // Dynamically tell v8 about our extensions now. OwnArrayPtr<const char*> extensionNames(new const char*[m_extensions.size()]); int index = 0; - for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) { - if (it->group && it->group != extensionGroup) + for (size_t i = 0; i < m_extensions.size(); ++i) { + if (m_extensions[i].group && m_extensions[i].group != extensionGroup) continue; // Note: we check the loader URL here instead of the document URL // because we might be currently loading an URL into a blank page. // See http://code.google.com/p/chromium/issues/detail?id=10924 - if (it->scheme.length() > 0 && (it->scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || it->scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol())) + if (m_extensions[i].scheme.length() > 0 && (m_extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || m_extensions[i].scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol())) continue; - extensionNames[index++] = it->extension->name(); + extensionNames[index++] = m_extensions[i].extension->name(); } v8::ExtensionConfiguration extensions(index, extensionNames.get()); result = v8::Context::New(&extensions, globalTemplate, global); @@ -967,12 +1055,14 @@ bool V8Proxy::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* windo // Wrap the window. V8DOMWrapper::setDOMWrapper(jsWindow, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); + V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); window->ref(); V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow)); // Insert the window instance as the prototype of the shadow object. v8::Handle<v8::Object> v8Global = context->Global(); + V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(v8Global->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); v8Global->Set(implicitProtoString, jsWindow); return true; } @@ -1021,7 +1111,6 @@ void V8Proxy::initContextIfNeeded() #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::JavaScriptInitTimeCounter); #endif - LOCK_V8; // Create a handle scope for all local handles. v8::HandleScope handleScope; @@ -1044,12 +1133,12 @@ void V8Proxy::initContextIfNeeded() isV8Initialized = true; } + m_context = createNewContext(m_global, 0); if (m_context.IsEmpty()) return; - // Starting from now, use local context only. - v8::Local<v8::Context> v8Context = context(); + v8::Local<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context); v8::Context::Scope contextScope(v8Context); // Store the first global object created so we can reuse it. @@ -1065,7 +1154,7 @@ void V8Proxy::initContextIfNeeded() #endif } - installHiddenObjectPrototype(m_context); + installHiddenObjectPrototype(v8Context); m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT)); // Bail out if allocation failed. if (m_wrapperBoilerplates.IsEmpty()) { @@ -1084,7 +1173,11 @@ void V8Proxy::initContextIfNeeded() setSecurityToken(); m_frame->loader()->client()->didCreateScriptContextForFrame(); - m_frame->loader()->dispatchWindowObjectAvailable(); + + // FIXME: This is wrong. We should actually do this for the proper world once + // we do isolated worlds the WebCore way. + m_frame->loader()->dispatchDidClearWindowObjectInWorld(0); + #ifdef ANDROID_INSTRUMENT android::TimeCounter::record(android::TimeCounter::JavaScriptInitTimeCounter, __FUNCTION__); #endif @@ -1162,14 +1255,30 @@ v8::Local<v8::Context> V8Proxy::context(Frame* frame) return context; } +v8::Local<v8::Context> V8Proxy::context() +{ + if (V8IsolatedWorld* world = V8IsolatedWorld::getEntered()) { + RefPtr<SharedPersistent<v8::Context> > context = world->sharedContext(); + if (m_frame != V8Proxy::retrieveFrame(context->get())) + return v8::Local<v8::Context>(); + return v8::Local<v8::Context>::New(context->get()); + } + return mainWorldContext(); +} + +v8::Local<v8::Context> V8Proxy::mainWorldContext() +{ + initContextIfNeeded(); + return v8::Local<v8::Context>::New(m_context); +} + v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame) { V8Proxy* proxy = retrieve(frame); if (!proxy) return v8::Local<v8::Context>(); - proxy->initContextIfNeeded(); - return proxy->context(); + return proxy->mainWorldContext(); } v8::Local<v8::Context> V8Proxy::currentContext() @@ -1238,7 +1347,7 @@ void V8Proxy::createUtilityContext() v8::Script::Compile(v8::String::New(frameSourceNameSource))->Run(); } -int V8Proxy::sourceLineNumber() +bool V8Proxy::sourceLineNumber(int& result) { #if PLATFORM(ANDROID) // TODO(andreip): consider V8's DEBUG flag here, rather than PLATFORM(ANDROID) @@ -1248,45 +1357,57 @@ int V8Proxy::sourceLineNumber() v8::HandleScope scope; v8::Handle<v8::Context> v8UtilityContext = V8Proxy::utilityContext(); if (v8UtilityContext.IsEmpty()) - return 0; + return false; v8::Context::Scope contextScope(v8UtilityContext); v8::Handle<v8::Function> frameSourceLine; frameSourceLine = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceLine"))); if (frameSourceLine.IsEmpty()) - return 0; - v8::Handle<v8::Value> result = v8::Debug::Call(frameSourceLine); - if (result.IsEmpty()) - return 0; - return result->Int32Value(); + return false; + v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceLine); + if (value.IsEmpty()) + return false; + result = value->Int32Value(); + return true; #endif } -String V8Proxy::sourceName() +bool V8Proxy::sourceName(String& result) { #if PLATFORM(ANDROID) - return String(); + return false; #else v8::HandleScope scope; v8::Handle<v8::Context> v8UtilityContext = utilityContext(); if (v8UtilityContext.IsEmpty()) - return String(); + return false; v8::Context::Scope contextScope(v8UtilityContext); v8::Handle<v8::Function> frameSourceName; frameSourceName = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceName"))); if (frameSourceName.IsEmpty()) - return String(); - return toWebCoreString(v8::Debug::Call(frameSourceName)); + return false; + v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceName); + if (value.IsEmpty()) + return false; + result = toWebCoreString(value); + return true; #endif } -void V8Proxy::registerExtensionWithV8(v8::Extension* extension) { +void V8Proxy::registerExtensionWithV8(v8::Extension* extension) +{ // If the extension exists in our list, it was already registered with V8. - for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) { - if (it->extension == extension) - return; + if (!registeredExtensionWithV8(extension)) + v8::RegisterExtension(extension); +} + +bool V8Proxy::registeredExtensionWithV8(v8::Extension* extension) +{ + for (size_t i = 0; i < m_extensions.size(); ++i) { + if (m_extensions[i].extension == extension) + return true; } - v8::RegisterExtension(extension); + return false; } void V8Proxy::registerExtension(v8::Extension* extension, const String& schemeRestriction) @@ -1313,20 +1434,24 @@ bool V8Proxy::setContextDebugId(int debugId) return false; v8::Context::Scope contextScope(m_context); - v8::Handle<v8::Object> contextData = v8::Object::New(); - contextData->Set(v8::String::New(kContextDebugDataType), v8::String::New("page")); - contextData->Set(v8::String::New(kContextDebugDataValue), v8::Integer::New(debugId)); - m_context->SetData(contextData); + + char buffer[32]; + snprintf(buffer, sizeof(buffer), "page,%d", debugId); + m_context->SetData(v8::String::New(buffer)); + return true; } int V8Proxy::contextDebugId(v8::Handle<v8::Context> context) { v8::HandleScope scope; - if (!context->GetData()->IsObject()) + if (!context->GetData()->IsString()) + return -1; + v8::String::AsciiValue ascii(context->GetData()); + char* comma = strnstr(*ascii, ",", ascii.length()); + if (!comma) return -1; - v8::Handle<v8::Value> data = context->GetData()->ToObject()->Get( v8::String::New(kContextDebugDataValue)); - return data->IsInt32() ? data->Int32Value() : -1; + return atoi(comma + 1); } v8::Handle<v8::Value> V8Proxy::getHiddenObjectPrototype(v8::Handle<v8::Context> context) @@ -1349,4 +1474,16 @@ void V8Proxy::installHiddenObjectPrototype(v8::Handle<v8::Context> context) context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype); } +v8::Local<v8::Context> toV8Context(ScriptExecutionContext* context, const WorldContextHandle& worldContext) +{ + if (context->isDocument()) { + if (V8Proxy* proxy = V8Proxy::retrieve(context)) + return worldContext.adjustedContext(proxy); + } else if (context->isWorkerContext()) { + if (WorkerContextExecutionProxy* proxy = static_cast<WorkerContext*>(context)->script()->proxy()) + return proxy->context(); + } + return v8::Local<v8::Context>(); +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h index d8f546c..900ee18 100644 --- a/WebCore/bindings/v8/V8Proxy.h +++ b/WebCore/bindings/v8/V8Proxy.h @@ -31,20 +31,14 @@ #ifndef V8Proxy_h #define V8Proxy_h -#include "Node.h" -#include "NodeFilter.h" -#include "PlatformString.h" // for WebCore::String #include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode #include "SecurityOrigin.h" // for WebCore::SecurityOrigin -#include "V8CustomBinding.h" -#include "V8DOMMap.h" +#include "SharedPersistent.h" +#include "V8AbstractEventListener.h" #include "V8DOMWrapper.h" -#include "V8EventListenerList.h" #include "V8GCController.h" #include "V8Index.h" -#include "V8Utilities.h" #include <v8.h> -#include <wtf/Assertions.h> #include <wtf/PassRefPtr.h> // so generated bindings don't have to #include <wtf/Vector.h> @@ -57,49 +51,15 @@ namespace WebCore { - class CSSRule; - class CSSRuleList; - class CSSStyleDeclaration; - class CSSValue; - class CSSValueList; - class ClientRectList; - class DOMImplementation; class DOMWindow; - class Document; - class Element; - class Event; - class EventListener; - class EventTarget; class Frame; - class HTMLCollection; - class HTMLDocument; - class HTMLElement; - class HTMLOptionsCollection; - class MediaList; - class MimeType; - class MimeTypeArray; - class NamedNodeMap; - class Navigator; class Node; - class NodeFilter; - class NodeList; - class Plugin; - class PluginArray; class SVGElement; -#if ENABLE(SVG) - class SVGElementInstance; -#endif - class Screen; class ScriptExecutionContext; -#if ENABLE(DOM_STORAGE) - class Storage; - class StorageEvent; -#endif class String; - class StyleSheet; - class StyleSheetList; class V8EventListener; - class V8ObjectEventListener; + class V8IsolatedWorld; + class WorldContextHandle; // FIXME: use standard logging facilities in WebCore. void logInfo(Frame*, const String& message, const String& url); @@ -123,6 +83,16 @@ namespace WebCore { void batchConfigureAttributes(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::ObjectTemplate>, const BatchedAttribute*, size_t attributeCount); + inline void configureAttribute(v8::Handle<v8::ObjectTemplate> instance, v8::Handle<v8::ObjectTemplate> proto, const BatchedAttribute& attribute) + { + (attribute.onProto ? proto : instance)->SetAccessor(v8::String::New(attribute.name), + attribute.getter, + attribute.setter, + attribute.data == V8ClassIndex::INVALID_CLASS_INDEX ? v8::Handle<v8::Value>() : v8::Integer::New(V8ClassIndex::ToInt(attribute.data)), + attribute.settings, + attribute.attribute); + } + // BatchedConstant translates into calls to Set() for setting up an object's // constants. It sets the constant on both the FunctionTemplate and the // ObjectTemplate. PropertyAttributes is always ReadOnly. @@ -133,6 +103,17 @@ namespace WebCore { void batchConfigureConstants(v8::Handle<v8::FunctionTemplate>, v8::Handle<v8::ObjectTemplate>, const BatchedConstant*, size_t constantCount); + struct BatchedCallback { + const char* const name; + v8::InvocationCallback callback; + }; + + void batchConfigureCallbacks(v8::Handle<v8::ObjectTemplate>, + v8::Handle<v8::Signature>, + v8::PropertyAttribute, + const BatchedCallback*, + size_t callbackCount); + const int kMaxRecursionDepth = 20; // Information about an extension that is registered for use with V8. If @@ -145,7 +126,7 @@ namespace WebCore { int group; v8::Extension* extension; }; - typedef WTF::Vector<V8ExtensionInfo> V8ExtensionList; + typedef WTF::Vector<V8ExtensionInfo> V8Extensions; class V8Proxy { public: @@ -158,7 +139,7 @@ namespace WebCore { GeneralError }; - explicit V8Proxy(Frame* frame) : m_frame(frame), m_inlineCode(false), m_timerCallback(false), m_recursion(0) { } + explicit V8Proxy(Frame*); ~V8Proxy(); @@ -194,14 +175,36 @@ namespace WebCore { // and clears all timeouts on the DOM window. void disconnectFrame(); - bool isEnabled(); - - V8EventListenerList* eventListeners() { return &m_eventListeners; } - V8EventListenerList* objectListeners() { return &m_objectListeners; } - #if ENABLE(SVG) static void setSVGContext(void*, SVGElement*); static SVGElement* svgContext(void*); + + // These helper functions are required in case we are given a PassRefPtr + // to a (possibly) newly created object and must prevent its reference + // count from dropping to zero as would happen in code like + // + // V8Proxy::setSVGContext(imp->getNewlyCreatedObject().get(), context); + // foo(imp->getNewlyCreatedObject().get()); + // + // In the above two lines each time getNewlyCreatedObject() is called it + // creates a new object because we don't ref() it. (So our attemts to + // associate a context with it fail.) Such code should be rewritten to + // + // foo(V8Proxy::withSVGContext(imp->getNewlyCreatedObject(), context).get()); + // + // where PassRefPtr::~PassRefPtr() is invoked only after foo() is + // called. + template <typename T> + static PassRefPtr<T> withSVGContext(PassRefPtr<T> object, SVGElement* context) + { + setSVGContext(object.get(), context); + return object; + } + static void* withSVGContext(void* object, SVGElement* context) + { + setSVGContext(object, context); + return object; + } #endif void setEventHandlerLineNumber(int lineNumber) { m_handlerLineNumber = lineNumber; } @@ -211,7 +214,7 @@ namespace WebCore { // global scope, its own prototypes for intrinsic JavaScript objects (String, // Array, and so-on), and its own wrappers for all DOM nodes and DOM // constructors. - void evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup); + void evaluateInIsolatedWorld(int worldId, const Vector<ScriptSourceCode>& sources, int extensionGroup); // Evaluate JavaScript in a new context. The script gets its own global scope // and its own prototypes for intrinsic JavaScript objects (String, Array, @@ -239,7 +242,12 @@ namespace WebCore { // To create JS Wrapper objects, we create a cache of a 'boiler plate' // object, and then simply Clone that object each time we need a new one. // This is faster than going through the full object creation process. - v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType); + v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType type) + { + int classIndex = V8ClassIndex::ToInt(type); + v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex)); + return clone.IsEmpty() ? createWrapperFromCacheSlowCase(type) : clone; + } // Returns the window object associated with a context. static DOMWindow* retrieveWindow(v8::Handle<v8::Context>); @@ -331,14 +339,16 @@ namespace WebCore { // Function for retrieving the line number and source name for the top // JavaScript stack frame. - static int sourceLineNumber(); - static String sourceName(); + // + // It will return true if the line number was successfully retrieved and written + // into the |result| parameter, otherwise the function will return false. It may + // fail due to a stck overflow in the underlying JavaScript implentation, handling + // of such exception is up to the caller. + static bool sourceLineNumber(int& result); + static bool sourceName(String& result); - // Returns a local handle of the context. - v8::Local<v8::Context> context() - { - return v8::Local<v8::Context>::New(m_context); - } + v8::Local<v8::Context> context(); + v8::Local<v8::Context> mainWorldContext(); bool setContextDebugId(int id); static int contextDebugId(v8::Handle<v8::Context>); @@ -365,10 +375,6 @@ namespace WebCore { void updateDocumentWrapper(v8::Handle<v8::Value> wrapper); private: - static const char* kContextDebugDataType; - static const char* kContextDebugDataValue; - - void disconnectEventListeners(); void setSecurityToken(); void clearDocumentWrapper(); @@ -382,6 +388,15 @@ namespace WebCore { // Dispose global handles of m_contexts and friends. void disposeContextHandles(); + // If m_recursionCount is 0, let LocalStorage know so we can release + // the storage mutex. + void releaseStorageMutex(); + + void resetIsolatedWorlds(); + + // Returns false when we're out of memory in V8. + bool setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContext); + static bool canAccessPrivate(DOMWindow*); static const char* rangeExceptionName(int exceptionCode); @@ -407,11 +422,15 @@ namespace WebCore { return v8::Local<v8::Context>::New(m_utilityContext); } + v8::Local<v8::Object> createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType); + static void registerExtensionWithV8(v8::Extension*); + static bool registeredExtensionWithV8(v8::Extension*); Frame* m_frame; v8::Persistent<v8::Context> m_context; + // For each possible type of wrapper, we keep a boilerplate object. // The boilerplate is used to create additional wrappers of the same // type. We keep a single persistent handle to an array of the @@ -426,14 +445,6 @@ namespace WebCore { int m_handlerLineNumber; - // A list of event listeners created for this frame, - // the list gets cleared when removing all timeouts. - V8EventListenerList m_eventListeners; - - // A list of event listeners create for XMLHttpRequest object for this frame, - // the list gets cleared when removing all timeouts. - V8EventListenerList m_objectListeners; - // True for <a href="javascript:foo()"> and false for <script>foo()</script>. // Only valid during execution. bool m_inlineCode; @@ -447,8 +458,18 @@ namespace WebCore { // excessive recursion in the binding layer. int m_recursion; - // List of extensions registered with the context. - static V8ExtensionList m_extensions; + // All of the extensions registered with the context. + static V8Extensions m_extensions; + + // The isolated worlds we are tracking for this frame. We hold them alive + // here so that they can be used again by future calls to + // evaluateInIsolatedWorld(). + // + // Note: although the pointer is raw, the instance is kept alive by a strong + // reference to the v8 context it contains, which is not made weak until we + // call world->destroy(). + typedef HashMap<int, V8IsolatedWorld*> IsolatedWorldMap; + IsolatedWorldMap m_isolatedWorlds; }; template <int tag, typename T> @@ -467,6 +488,8 @@ namespace WebCore { } + v8::Local<v8::Context> toV8Context(ScriptExecutionContext*, const WorldContextHandle& worldContext); + // Used by an interceptor callback that it hasn't found anything to // intercept. inline static v8::Local<v8::Object> notHandledByInterceptor() diff --git a/WebCore/bindings/v8/V8Utilities.cpp b/WebCore/bindings/v8/V8Utilities.cpp index c1ac6d4..c547cc7 100644 --- a/WebCore/bindings/v8/V8Utilities.cpp +++ b/WebCore/bindings/v8/V8Utilities.cpp @@ -33,8 +33,15 @@ #include <v8.h> +#include "Document.h" +#include "Frame.h" +#include "ScriptExecutionContext.h" +#include "ScriptState.h" #include "V8CustomBinding.h" +#include "V8Binding.h" #include "V8Proxy.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" #include <wtf/Assertions.h> #include "Frame.h" @@ -43,7 +50,7 @@ namespace WebCore { // Use an array to hold dependents. It works like a ref-counted scheme. // A value can be added more than once to the DOM object. -void createHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) +void createHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) { v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); if (cache->IsNull() || cache->IsUndefined()) { @@ -55,7 +62,7 @@ void createHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> v cacheArray->Set(v8::Integer::New(cacheArray->Length()), value); } -void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) +void removeHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) { v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); if (!cache->IsArray()) @@ -69,6 +76,24 @@ void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> v } } } + +void transferHiddenDependency(v8::Handle<v8::Object> object, + EventListener* oldValue, + v8::Local<v8::Value> newValue, + int cacheIndex) +{ + if (oldValue) { + V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(oldValue); + if (oldListener) { + v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject(); + if (!oldListenerObject.IsEmpty()) + removeHiddenDependency(object, oldListenerObject, cacheIndex); + } + } + if (!newValue->IsNull() && !newValue->IsUndefined()) + createHiddenDependency(object, newValue, cacheIndex); +} + bool processingUserGesture() { @@ -98,7 +123,55 @@ void navigateIfAllowed(Frame* frame, const KURL& url, bool lockHistory, bool loc return; if (!protocolIsJavaScript(url) || ScriptController::isSafeScript(frame)) - frame->loader()->scheduleLocationChange(url.string(), callingFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture()); + frame->redirectScheduler()->scheduleLocationChange(url.string(), callingFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture()); +} + +ScriptExecutionContext* getScriptExecutionContext(ScriptState* scriptState) +{ +#if ENABLE(WORKERS) + WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + if (proxy) + return proxy->workerContext()->scriptExecutionContext(); +#endif + + if (scriptState) + return scriptState->frame()->document()->scriptExecutionContext(); + else { + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (frame) + return frame->document()->scriptExecutionContext(); + } + + return 0; +} + +void reportException(ScriptState* scriptState, v8::TryCatch& exceptionCatcher) +{ + String errorMessage; + int lineNumber = 0; + String sourceURL; + + // There can be a situation that an exception is thrown without setting a message. + v8::Local<v8::Message> message = exceptionCatcher.Message(); + if (message.IsEmpty()) { + v8::Local<v8::String> exceptionString = exceptionCatcher.Exception()->ToString(); + // Conversion of the exception object to string can fail if an + // exception is thrown during conversion. + if (!exceptionString.IsEmpty()) + errorMessage = toWebCoreString(exceptionString); + } else { + errorMessage = toWebCoreString(message->Get()); + lineNumber = message->GetLineNumber(); + sourceURL = toWebCoreString(message->GetScriptResourceName()); + } + + // Do not report the exception if the current execution context is Document because we do not want to lead to duplicate error messages in the console. + // FIXME (31171): need better design to solve the duplicate error message reporting problem. + ScriptExecutionContext* context = getScriptExecutionContext(scriptState); + // During the frame teardown, there may not be a valid context. + if (context && !context->isDocument()) + context->reportException(errorMessage, lineNumber, sourceURL); + exceptionCatcher.Reset(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8Utilities.h b/WebCore/bindings/v8/V8Utilities.h index 3e59d34..944823a 100644 --- a/WebCore/bindings/v8/V8Utilities.h +++ b/WebCore/bindings/v8/V8Utilities.h @@ -31,30 +31,36 @@ #ifndef V8Utilities_h #define V8Utilities_h -#if ENABLE(V8_LOCKERS) -// TODO(benm): Need to re-add in locking for V8. We lost some of the lock points during the merge. Define it to void here so we don't lock some of the time. -#define LOCK_V8 ((void) 0) -#else -#define LOCK_V8 ((void) 0) -#endif - #include <v8.h> namespace WebCore { + class EventListener; class Frame; class KURL; + class ScriptExecutionContext; + class ScriptState; class String; // Use an array to hold dependents. It works like a ref-counted scheme. A value can be added more than once to the DOM object. - void createHiddenDependency(v8::Local<v8::Object>, v8::Local<v8::Value>, int cacheIndex); - void removeHiddenDependency(v8::Local<v8::Object>, v8::Local<v8::Value>, int cacheIndex); - + void createHiddenDependency(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex); + void removeHiddenDependency(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex); + + // Combo create/remove, for generated event-handler-setter bindings: + void transferHiddenDependency(v8::Handle<v8::Object>, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex); + bool processingUserGesture(); bool shouldAllowNavigation(Frame*); KURL completeURL(const String& relativeURL); void navigateIfAllowed(Frame*, const KURL&, bool lockHistory, bool lockBackForwardList); + ScriptExecutionContext* getScriptExecutionContext(ScriptState*); + inline ScriptExecutionContext* getScriptExecutionContext() { + return getScriptExecutionContext(0); + } + + void reportException(ScriptState*, v8::TryCatch&); + class AllowAllocation { public: inline AllowAllocation() diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp index 862cd2d..e5356de 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp @@ -36,54 +36,54 @@ #include "Event.h" #include "V8Binding.h" -#include "V8Utilities.h" +#include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" namespace WebCore { -V8WorkerContextEventListener::V8WorkerContextEventListener(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline) - : V8EventListener(0, listener, isInline) - , m_proxy(proxy) +static WorkerContextExecutionProxy* workerProxy(ScriptExecutionContext* context) { + ASSERT(context->isWorkerContext()); + WorkerContext* workerContext = static_cast<WorkerContext*>(context); + return workerContext->script()->proxy(); } -V8WorkerContextEventListener::~V8WorkerContextEventListener() +V8WorkerContextEventListener::V8WorkerContextEventListener(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext) + : V8EventListener(listener, isInline, worldContext) { - if (m_proxy) - m_proxy->removeEventListener(this); - disposeListenerObject(); } -void V8WorkerContextEventListener::handleEvent(Event* event, bool isWindowEvent) +void V8WorkerContextEventListener::handleEvent(ScriptExecutionContext* context, Event* event) { - // Is the EventListener disconnected? - if (disconnected()) + if (!context) return; // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); - LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = m_proxy->context(); - if (context.IsEmpty()) + WorkerContextExecutionProxy* proxy = workerProxy(context); + if (!proxy) + return; + + v8::Handle<v8::Context> v8Context = proxy->context(); + if (v8Context.IsEmpty()) return; // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); // Get the V8 wrapper for the event object. v8::Handle<v8::Value> jsEvent = WorkerContextExecutionProxy::convertEventToV8Object(event); - invokeEventHandler(context, event, jsEvent, isWindowEvent); + invokeEventHandler(context, event, jsEvent); } -bool V8WorkerContextEventListener::reportError(const String& message, const String& url, int lineNumber) +bool V8WorkerContextEventListener::reportError(ScriptExecutionContext* context, const String& message, const String& url, int lineNumber) { - // Is the EventListener disconnected? - if (disconnected()) + if (!context) return false; // The callback function can clear the event listener and destroy 'this' object. Keep a local reference to it. @@ -91,13 +91,18 @@ bool V8WorkerContextEventListener::reportError(const String& message, const Stri v8::HandleScope handleScope; - v8::Handle<v8::Context> context = m_proxy->context(); - if (context.IsEmpty()) + WorkerContextExecutionProxy* proxy = workerProxy(context); + if (!proxy) + return false; + + v8::Handle<v8::Context> v8Context = proxy->context(); + if (v8Context.IsEmpty()) return false; // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); + v8::Local<v8::Object> listener = getListenerObject(context); v8::Local<v8::Value> returnValue; { // Catch exceptions thrown in calling the function so they do not propagate to javascript code that caused the event to fire. @@ -105,8 +110,8 @@ bool V8WorkerContextEventListener::reportError(const String& message, const Stri tryCatch.SetVerbose(true); // Call the function. - if (!m_listener.IsEmpty() && m_listener->IsFunction()) { - v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener)); + if (!listener.IsEmpty() && listener->IsFunction()) { + v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); v8::Handle<v8::Value> parameters[3] = { v8String(message), v8String(url), v8::Integer::New(lineNumber) }; @@ -126,28 +131,28 @@ bool V8WorkerContextEventListener::reportError(const String& message, const Stri return errorHandled; } -v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event, bool isWindowEvent) +v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Function> handlerFunction = getListenerFunction(); - v8::Local<v8::Object> receiver = getReceiverObject(event, isWindowEvent); + v8::Local<v8::Function> handlerFunction = getListenerFunction(context); + v8::Local<v8::Object> receiver = getReceiverObject(context, event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); v8::Handle<v8::Value> parameters[1] = { jsEvent }; v8::Local<v8::Value> result = handlerFunction->Call(receiver, 1, parameters); - m_proxy->trackEvent(event); + if (WorkerContextExecutionProxy* proxy = workerProxy(context)) + proxy->trackEvent(event); return result; } -v8::Local<v8::Object> V8WorkerContextEventListener::getReceiverObject(Event* event, bool isWindowEvent) +v8::Local<v8::Object> V8WorkerContextEventListener::getReceiverObject(ScriptExecutionContext* context, Event* event) { - if (!m_listener.IsEmpty() && !m_listener->IsFunction()) - return v8::Local<v8::Object>::New(m_listener); + v8::Local<v8::Object> listener = getListenerObject(context); - if (isWindowEvent) - return v8::Context::GetCurrent()->Global(); + if (!listener.IsEmpty() && !listener->IsFunction()) + return listener; EventTarget* target = event->currentTarget(); v8::Handle<v8::Value> value = WorkerContextExecutionProxy::convertEventTargetToV8Object(target); diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.h b/WebCore/bindings/v8/V8WorkerContextEventListener.h index c901c51..4487497 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.h +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.h @@ -44,24 +44,19 @@ namespace WebCore { class V8WorkerContextEventListener : public V8EventListener { public: - static PassRefPtr<V8WorkerContextEventListener> create(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline) + static PassRefPtr<V8WorkerContextEventListener> create(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext) { - return adoptRef(new V8WorkerContextEventListener(proxy, listener, isInline)); + return adoptRef(new V8WorkerContextEventListener(listener, isInline, worldContext)); } - V8WorkerContextEventListener(WorkerContextExecutionProxy*, v8::Local<v8::Object> listener, bool isInline); - virtual ~V8WorkerContextEventListener(); - virtual void handleEvent(Event*, bool isWindowEvent); - virtual bool reportError(const String& message, const String& url, int lineNumber); - virtual bool disconnected() const { return !m_proxy; } - - WorkerContextExecutionProxy* proxy() const { return m_proxy; } - void disconnect() { m_proxy = 0; } + virtual void handleEvent(ScriptExecutionContext*, Event*); + virtual bool reportError(ScriptExecutionContext*, const String& message, const String& url, int lineNumber); private: - virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*, bool isWindowEvent); - v8::Local<v8::Object> getReceiverObject(Event*, bool isWindowEvent); - WorkerContextExecutionProxy* m_proxy; + V8WorkerContextEventListener(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext); + + virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); + v8::Local<v8::Object> getReceiverObject(ScriptExecutionContext*, Event*); }; } // namespace WebCore diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp index ba858cf..8c66d7b 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp @@ -38,15 +38,21 @@ #include "DOMCoreException.h" #include "DedicatedWorkerContext.h" #include "Event.h" +#include "Notification.h" +#include "NotificationCenter.h" #include "EventException.h" #include "MessagePort.h" #include "RangeException.h" +#include "SharedWorker.h" +#include "SharedWorkerContext.h" #include "V8Binding.h" #include "V8DOMMap.h" #include "V8Index.h" #include "V8Proxy.h" #include "V8WorkerContextEventListener.h" -#include "V8WorkerContextObjectEventListener.h" +#if ENABLE(WEB_SOCKETS) +#include "WebSocket.h" +#endif #include "Worker.h" #include "WorkerContext.h" #include "WorkerLocation.h" @@ -77,14 +83,6 @@ WorkerContextExecutionProxy::~WorkerContextExecutionProxy() void WorkerContextExecutionProxy::dispose() { - // Disconnect all event listeners. - if (m_listeners.get()) { - for (V8EventListenerList::iterator iterator(m_listeners->begin()); iterator != m_listeners->end(); ++iterator) - static_cast<V8WorkerContextEventListener*>(*iterator)->disconnect(); - - m_listeners->clear(); - } - // Detach all events from their JS wrappers. for (size_t eventIndex = 0; eventIndex < m_events.size(); ++eventIndex) { Event* event = m_events[eventIndex]; @@ -119,7 +117,6 @@ void WorkerContextExecutionProxy::initV8IfNeeded() { static bool v8Initialized = false; - LOCK_V8; if (v8Initialized) return; @@ -131,6 +128,12 @@ void WorkerContextExecutionProxy::initV8IfNeeded() const int workerThreadPreemptionIntervalMs = 5; v8::Locker::StartPreemption(workerThreadPreemptionIntervalMs); #endif + + v8::ResourceConstraints resource_constraints; + uint32_t here; + resource_constraints.set_stack_limit(&here - kWorkerMaxStackSize / sizeof(uint32_t*)); + v8::SetResourceConstraints(&resource_constraints); + v8Initialized = true; } @@ -152,7 +155,12 @@ void WorkerContextExecutionProxy::initContextIfNeeded() v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); // Create a new JS object and use it as the prototype for the shadow global object. - v8::Handle<v8::Function> workerContextConstructor = V8DOMWrapper::getConstructorForContext(V8ClassIndex::DEDICATEDWORKERCONTEXT, context); + V8ClassIndex::V8WrapperType contextType = V8ClassIndex::DEDICATEDWORKERCONTEXT; +#if ENABLE(SHARED_WORKERS) + if (!m_workerContext->isDedicatedWorkerContext()) + contextType = V8ClassIndex::SHAREDWORKERCONTEXT; +#endif + v8::Handle<v8::Function> workerContextConstructor = V8DOMWrapper::getConstructorForContext(contextType, context); v8::Local<v8::Object> jsWorkerContext = SafeAllocation::newInstance(workerContextConstructor); // Bail out if allocation failed. if (jsWorkerContext.IsEmpty()) { @@ -161,7 +169,7 @@ void WorkerContextExecutionProxy::initContextIfNeeded() } // Wrap the object. - V8DOMWrapper::setDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(V8ClassIndex::DEDICATEDWORKERCONTEXT), m_workerContext); + V8DOMWrapper::setDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(contextType), m_workerContext); V8DOMWrapper::setJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext)); m_workerContext->ref(); @@ -169,8 +177,6 @@ void WorkerContextExecutionProxy::initContextIfNeeded() // Insert the object instance as the prototype of the shadow object. v8::Handle<v8::Object> globalObject = m_context->Global(); globalObject->Set(implicitProtoString, jsWorkerContext); - - m_listeners.set(new V8EventListenerList()); } v8::Handle<v8::Value> WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl) @@ -178,7 +184,11 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::convertToV8Object(V8ClassInde if (!impl) return v8::Null(); - if (type == V8ClassIndex::DEDICATEDWORKERCONTEXT) + if (type == V8ClassIndex::DEDICATEDWORKERCONTEXT +#if ENABLE(SHARED_WORKERS) + || type == V8ClassIndex::SHAREDWORKERCONTEXT +#endif + ) return convertWorkerContextToV8Object(static_cast<WorkerContext*>(impl)); bool isActiveDomObject = false; @@ -224,6 +234,14 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::convertToV8Object(V8ClassInde case V8ClassIndex::WORKERNAVIGATOR: static_cast<WorkerNavigator*>(impl)->ref(); break; +#if ENABLE(NOTIFICATIONS) + case V8ClassIndex::NOTIFICATIONCENTER: + static_cast<NotificationCenter*>(impl)->ref(); + break; + case V8ClassIndex::NOTIFICATION: + static_cast<Notification*>(impl)->ref(); + break; +#endif case V8ClassIndex::DOMCOREEXCEPTION: static_cast<DOMCoreException*>(impl)->ref(); break; @@ -282,10 +300,22 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::convertEventTargetToV8Object( if (workerContext) return convertWorkerContextToV8Object(workerContext); +#if ENABLE(SHARED_WORKERS) + SharedWorkerContext* sharedWorkerContext = target->toSharedWorkerContext(); + if (sharedWorkerContext) + return convertWorkerContextToV8Object(sharedWorkerContext); +#endif + Worker* worker = target->toWorker(); if (worker) return convertToV8Object(V8ClassIndex::WORKER, worker); +#if ENABLE(SHARED_WORKERS) + SharedWorker* sharedWorker = target->toSharedWorker(); + if (sharedWorker) + return convertToV8Object(V8ClassIndex::SHAREDWORKER, sharedWorker); +#endif + XMLHttpRequest* xhr = target->toXMLHttpRequest(); if (xhr) return convertToV8Object(V8ClassIndex::XMLHTTPREQUEST, xhr); @@ -337,7 +367,6 @@ bool WorkerContextExecutionProxy::forgetV8EventObject(Event* event) ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, int baseLine, WorkerContextExecutionState* state) { - LOCK_V8; v8::HandleScope hs; initContextIfNeeded(); @@ -398,40 +427,9 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Scrip return result; } -PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListenerHelper(v8::Local<v8::Value> object, bool isInline, bool findOnly, bool createObjectEventListener) -{ - if (!object->IsObject()) - return 0; - - V8EventListener* listener = m_listeners->find(object->ToObject(), isInline); - if (findOnly) - return listener; - - // Create a new one, and add to cache. - RefPtr<V8EventListener> newListener; - if (createObjectEventListener) - newListener = V8WorkerContextObjectEventListener::create(this, v8::Local<v8::Object>::Cast(object), isInline); - else - newListener = V8WorkerContextEventListener::create(this, v8::Local<v8::Object>::Cast(object), isInline); - - m_listeners->add(newListener.get()); - - return newListener.release(); -} - PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly) { - return findOrCreateEventListenerHelper(object, isInline, findOnly, false); -} - -PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly) -{ - return findOrCreateEventListenerHelper(object, isInline, findOnly, true); -} - -void WorkerContextExecutionProxy::removeEventListener(V8EventListener* listener) -{ - m_listeners->remove(listener); + return findOnly ? V8EventListenerList::findWrapper(object, isInline) : V8EventListenerList::findOrCreateWrapper<V8WorkerContextEventListener>(object, isInline); } void WorkerContextExecutionProxy::trackEvent(Event* event) diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.h b/WebCore/bindings/v8/WorkerContextExecutionProxy.h index 75024df..3b8ab9e 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.h +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.h @@ -64,12 +64,8 @@ namespace WebCore { WorkerContextExecutionProxy(WorkerContext*); ~WorkerContextExecutionProxy(); - void removeEventListener(V8EventListener*); - // Finds/creates event listener wrappers. PassRefPtr<V8EventListener> findOrCreateEventListener(v8::Local<v8::Value> listener, bool isInline, bool findOnly); - PassRefPtr<V8EventListener> findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly); - PassRefPtr<V8EventListener> findOrCreateEventListenerHelper(v8::Local<v8::Value> object, bool isInline, bool findOnly, bool createObjectEventListener); // Track the event so that we can detach it from the JS wrapper when a worker // terminates. This is needed because we need to be able to dispose these @@ -111,11 +107,12 @@ namespace WebCore { static bool forgetV8EventObject(Event*); + static const int kWorkerMaxStackSize = 500 * 1024; + WorkerContext* m_workerContext; v8::Persistent<v8::Context> m_context; int m_recursion; - OwnPtr<V8EventListenerList> m_listeners; Vector<Event*> m_events; }; diff --git a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp b/WebCore/bindings/v8/WorldContextHandle.cpp index ce56563..eb83586 100644 --- a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp +++ b/WebCore/bindings/v8/WorldContextHandle.cpp @@ -29,31 +29,29 @@ */ #include "config.h" +#include "WorldContextHandle.h" -#if ENABLE(WORKERS) - -#include "V8WorkerContextObjectEventListener.h" - -#include "WorkerContextExecutionProxy.h" +#include "V8IsolatedWorld.h" namespace WebCore { -static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* parameter) +WorldContextHandle::WorldContextHandle(WorldToUse worldToUse) + : m_worldToUse(worldToUse) { - V8WorkerContextObjectEventListener* listener = static_cast<V8WorkerContextObjectEventListener*>(parameter); + if (worldToUse == UseMainWorld) + return; - // Remove the wrapper - listener->proxy()->removeEventListener(listener); - - listener->disposeListenerObject(); + if (V8IsolatedWorld* world = V8IsolatedWorld::getEntered()) + m_context = world->sharedContext(); } -V8WorkerContextObjectEventListener::V8WorkerContextObjectEventListener(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline) - : V8WorkerContextEventListener(proxy, listener, isInline) +v8::Local<v8::Context> WorldContextHandle::adjustedContext(V8Proxy* proxy) const { - m_listener.MakeWeak(this, weakObjectEventListenerCallback); + if (m_worldToUse == UseMainWorld) + return proxy->mainWorldContext(); + if (!m_context || m_context->get().IsEmpty()) + return proxy->context(); + return v8::Local<v8::Context>::New(m_context->get()); } } // namespace WebCore - -#endif // WORKERS diff --git a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.h b/WebCore/bindings/v8/WorldContextHandle.h index 6471637..ad0983e 100644 --- a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.h +++ b/WebCore/bindings/v8/WorldContextHandle.h @@ -28,32 +28,30 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef V8WorkerContextObjectEventListener_h -#define V8WorkerContextObjectEventListener_h +#ifndef WorldContextHandle_h +#define WorldContextHandle_h -#if ENABLE(WORKERS) +#include "SharedPersistent.h" -#include "V8WorkerContextEventListener.h" #include <v8.h> -#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> namespace WebCore { - class WorkerContextExecutionProxy; +class V8Proxy; - class V8WorkerContextObjectEventListener : public V8WorkerContextEventListener { - public: - static PassRefPtr<V8WorkerContextObjectEventListener> create(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline) - { - return adoptRef(new V8WorkerContextObjectEventListener(proxy, listener, isInline)); - } +enum WorldToUse { UseMainWorld, UseCurrentWorld }; - private: - V8WorkerContextObjectEventListener(WorkerContextExecutionProxy*, v8::Local<v8::Object> listener, bool isInline); - }; +class WorldContextHandle { +public: + WorldContextHandle(WorldToUse); + v8::Local<v8::Context> adjustedContext(V8Proxy*) const; -} // namespace WebCore +private: + WorldToUse m_worldToUse; + RefPtr<SharedPersistent<v8::Context> > m_context; +}; -#endif // WORKERS +} // namespace WebCore -#endif // V8WorkerContextObjectEventListener_h +#endif // WorldContextHandle_h diff --git a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp index ce759eb..0240895 100644 --- a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp @@ -38,75 +38,18 @@ #include "ScriptExecutionContext.h" #include "V8Binding.h" #include "V8CustomBinding.h" -#include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContextExecutionProxy.h" namespace WebCore { -PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) -{ - if (worker->scriptExecutionContext()->isWorkerContext()) { - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - ASSERT(workerContextProxy); - return workerContextProxy->findOrCreateObjectEventListener(value, isAttribute, findOnly); - } - - V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext()); - if (proxy) { - V8EventListenerList* list = proxy->objectListeners(); - return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); - } - - return 0; -} - -ACCESSOR_GETTER(AbstractWorkerOnerror) -{ - INC_STATS(L"DOM.AbstractWorker.onerror._get"); - AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, info.Holder()); - if (worker->onerror()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onerror()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(AbstractWorkerOnerror) -{ - INC_STATS(L"DOM.AbstractWorker.onerror._set"); - AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, info.Holder()); - V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onerror()); - if (value->IsNull()) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kAbstractWorkerRequestCacheIndex); - } - - // Clear the listener. - worker->setOnerror(0); - } else { - RefPtr<EventListener> listener = getEventListener(worker, value, true, false); - if (listener) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kAbstractWorkerRequestCacheIndex); - } - - worker->setOnerror(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kAbstractWorkerRequestCacheIndex); - } - } -} - CALLBACK_FUNC_DECL(AbstractWorkerAddEventListener) { INC_STATS(L"DOM.AbstractWorker.addEventListener()"); AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder()); - RefPtr<EventListener> listener = getEventListener(worker, args[1], false, false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOrCreate); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -122,7 +65,7 @@ CALLBACK_FUNC_DECL(AbstractWorkerRemoveEventListener) INC_STATS(L"DOM.AbstractWorker.removeEventListener()"); AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder()); - RefPtr<EventListener> listener = getEventListener(worker, args[1], false, true); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOnly); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); diff --git a/WebCore/bindings/v8/V8ObjectEventListener.h b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp index 3c5ae10..b44e074 100644 --- a/WebCore/bindings/v8/V8ObjectEventListener.h +++ b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,32 +28,29 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef V8ObjectEventListener_h -#define V8ObjectEventListener_h +#include "config.h" -#include "V8CustomEventListener.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" #include <v8.h> -#include <wtf/PassRefPtr.h> namespace WebCore { - class Frame; - - // V8ObjectEventListener is a special listener wrapper for objects not in the DOM. It keeps the JS listener as a weak pointer. - class V8ObjectEventListener : public V8EventListener { - public: - static PassRefPtr<V8ObjectEventListener> create(Frame* frame, v8::Local<v8::Object> listener, bool isInline) - { - return adoptRef(new V8ObjectEventListener(frame, listener, isInline)); - } - - virtual bool isObjectListener() const { return true; } - - private: - V8ObjectEventListener(Frame*, v8::Local<v8::Object> listener, bool isInline); - virtual ~V8ObjectEventListener(); - }; +CALLBACK_FUNC_DECL(ConsoleProfile) +{ + INC_STATS("console.profile()"); + v8::HandleScope scope; + v8::Context::Scope context_scope(v8::Context::GetCurrent()); + v8::V8::ResumeProfiler(); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleProfileEnd) +{ + INC_STATS("console.profileEnd()"); + v8::V8::PauseProfiler(); + return v8::Undefined(); +} } // namespace WebCore - -#endif // V8ObjectEventListener_h diff --git a/WebCore/bindings/v8/custom/V8CoordinatesCustom.cpp b/WebCore/bindings/v8/custom/V8CoordinatesCustom.cpp index 09522ba..1c07f29 100644 --- a/WebCore/bindings/v8/custom/V8CoordinatesCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CoordinatesCustom.cpp @@ -1,78 +1,75 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright 2009, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" +#include "Coordinates.h" -#include "V8Coordinates.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Proxy.h" -#include "Coordinates.h" - namespace WebCore { - ACCESSOR_GETTER(CoordinatesAltitude) { - INC_STATS("DOM.Coordinates.altitude._get"); - v8::Handle<v8::Object> holder = info.Holder(); - Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); - if (!imp->canProvideAltitude()) - return v8::Null(); - return v8::Number::New(imp->altitude()); - } +ACCESSOR_GETTER(CoordinatesAltitude) +{ + INC_STATS("DOM.Coordinates.altitude._get"); + v8::Handle<v8::Object> holder = info.Holder(); + Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); + if (!imp->canProvideAltitude()) + return v8::Null(); + return v8::Number::New(imp->altitude()); +} - ACCESSOR_GETTER(CoordinatesAltitudeAccuracy) { - INC_STATS("DOM.Coordinates.altitudeAccuracy._get"); - v8::Handle<v8::Object> holder = info.Holder(); - Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); - if (!imp->canProvideAltitudeAccuracy()) - return v8::Null(); - return v8::Number::New(imp->altitudeAccuracy()); - } +ACCESSOR_GETTER(CoordinatesAltitudeAccuracy) +{ + INC_STATS("DOM.Coordinates.altitudeAccuracy._get"); + v8::Handle<v8::Object> holder = info.Holder(); + Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); + if (!imp->canProvideAltitudeAccuracy()) + return v8::Null(); + return v8::Number::New(imp->altitudeAccuracy()); +} - ACCESSOR_GETTER(CoordinatesHeading) { - INC_STATS("DOM.Coordinates.heading._get"); - v8::Handle<v8::Object> holder = info.Holder(); - Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); - if (!imp->canProvideHeading()) - return v8::Null(); - return v8::Number::New(imp->heading()); - } +ACCESSOR_GETTER(CoordinatesHeading) +{ + INC_STATS("DOM.Coordinates.heading._get"); + v8::Handle<v8::Object> holder = info.Holder(); + Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); + if (!imp->canProvideHeading()) + return v8::Null(); + return v8::Number::New(imp->heading()); +} - ACCESSOR_GETTER(CoordinatesSpeed) { - INC_STATS("DOM.Coordinates.speed._get"); - v8::Handle<v8::Object> holder = info.Holder(); - Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); - if (!imp->canProvideSpeed()) - return v8::Null(); - return v8::Number::New(imp->speed()); - } +ACCESSOR_GETTER(CoordinatesSpeed) +{ + INC_STATS("DOM.Coordinates.speed._get"); + v8::Handle<v8::Object> holder = info.Holder(); + Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); + if (!imp->canProvideSpeed()) + return v8::Null(); + return v8::Number::New(imp->speed()); +} } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.h b/WebCore/bindings/v8/custom/V8CustomBinding.h index 22b4a94..e7670b7 100644 --- a/WebCore/bindings/v8/custom/V8CustomBinding.h +++ b/WebCore/bindings/v8/custom/V8CustomBinding.h @@ -78,6 +78,8 @@ struct NPObject; bool V8Custom::v8##NAME##IndexedSecurityCheck(v8::Local<v8::Object> host, \ uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +#define ACCESSOR_RUNTIME_ENABLER(NAME) bool V8Custom::v8##NAME##Enabled() + namespace WebCore { class DOMWindow; @@ -118,21 +120,38 @@ namespace WebCore { static const int kMessageChannelInternalFieldCount = kDefaultWrapperInternalFieldCount + 2; static const int kMessagePortRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kMessagePortEntangledPortIndex = kDefaultWrapperInternalFieldCount + 1; - static const int kMessagePortInternalFieldCount = kDefaultWrapperInternalFieldCount + 2; + static const int kMessagePortInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; #if ENABLE(WORKERS) - static const int kWorkerRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + static const int kAbstractWorkerRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kAbstractWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kWorkerRequestCacheIndex = kAbstractWorkerInternalFieldCount + 0; + static const int kWorkerInternalFieldCount = kAbstractWorkerInternalFieldCount + 1; static const int kWorkerContextRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; static const int kWorkerContextMinimumInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; static const int kDedicatedWorkerContextRequestCacheIndex = kWorkerContextMinimumInternalFieldCount + 0; static const int kDedicatedWorkerContextInternalFieldCount = kWorkerContextMinimumInternalFieldCount + 1; +#endif - static const int kAbstractWorkerRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kAbstractWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; +#if ENABLE(SHARED_WORKERS) + static const int kSharedWorkerRequestCacheIndex = kAbstractWorkerInternalFieldCount + 0; + static const int kSharedWorkerInternalFieldCount = kAbstractWorkerInternalFieldCount + 1; + + static const int kSharedWorkerContextRequestCacheIndex = kWorkerContextMinimumInternalFieldCount + 0; + static const int kSharedWorkerContextInternalFieldCount = kWorkerContextMinimumInternalFieldCount + 1; +#endif + +#if ENABLE(NOTIFICATIONS) + static const int kNotificationRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kNotificationInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; +#endif + +#if ENABLE(SVG) + static const int kSVGElementInstanceEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kSVGElementInstanceInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; #endif static const int kDOMWindowConsoleIndex = kDefaultWrapperInternalFieldCount + 0; @@ -148,16 +167,25 @@ namespace WebCore { static const int kDOMWindowToolbarIndex = kDefaultWrapperInternalFieldCount + 10; static const int kDOMWindowLocationIndex = kDefaultWrapperInternalFieldCount + 11; static const int kDOMWindowDOMSelectionIndex = kDefaultWrapperInternalFieldCount + 12; - static const int kDOMWindowInternalFieldCount = kDefaultWrapperInternalFieldCount + 13; + static const int kDOMWindowEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 13; + static const int kDOMWindowEnteredIsolatedWorldIndex = kDefaultWrapperInternalFieldCount + 14; + static const int kDOMWindowInternalFieldCount = kDefaultWrapperInternalFieldCount + 15; static const int kStyleSheetOwnerNodeIndex = kDefaultWrapperInternalFieldCount + 0; static const int kStyleSheetInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + static const int kNamedNodeMapOwnerNodeIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kNamedNodeMapInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; #if ENABLE(OFFLINE_WEB_APPLICATIONS) static const int kDOMApplicationCacheCacheIndex = kDefaultWrapperInternalFieldCount + 0; static const int kDOMApplicationCacheFieldCount = kDefaultWrapperInternalFieldCount + 1; #endif +#if ENABLE(WEB_SOCKETS) + static const int kWebSocketCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kWebSocketInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; +#endif + #define DECLARE_PROPERTY_ACCESSOR_GETTER(NAME) \ static v8::Handle<v8::Value> v8##NAME##AccessorGetter( \ v8::Local<v8::String> name, const v8::AccessorInfo& info) @@ -216,13 +244,27 @@ namespace WebCore { static bool v8##NAME##IndexedSecurityCheck(v8::Local<v8::Object> host, \ uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +#define DECLARE_ACCESSOR_RUNTIME_ENABLER(NAME) static bool v8##NAME##Enabled() + DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DStrokeStyle); DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DFillStyle); - DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowEvent); + DECLARE_PROPERTY_ACCESSOR(DOMWindowEvent); DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowCrypto); DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowLocation); DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowOpener); +#if ENABLE(VIDEO) + DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowAudio); + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowAudio); + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLMediaElement); + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLAudioElement); + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLVideoElement); + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowMediaError); +#endif + + DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowImage); + DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowOption); + DECLARE_PROPERTY_ACCESSOR(DocumentLocation); DECLARE_PROPERTY_ACCESSOR(DocumentImplementation); DECLARE_PROPERTY_ACCESSOR_GETTER(EventSrcElement); @@ -231,7 +273,6 @@ namespace WebCore { DECLARE_PROPERTY_ACCESSOR_GETTER(EventClipboardData); DECLARE_PROPERTY_ACCESSOR(DOMWindowEventHandler); - DECLARE_PROPERTY_ACCESSOR(NodeEventHandler); DECLARE_CALLBACK(HTMLCanvasElementGetContext); @@ -258,6 +299,10 @@ namespace WebCore { DECLARE_CALLBACK(HTMLCollectionNamedItem); DECLARE_CALLBACK(HTMLCollectionCallAsFunction); + DECLARE_CALLBACK(HTMLAllCollectionItem); + DECLARE_CALLBACK(HTMLAllCollectionNamedItem); + DECLARE_CALLBACK(HTMLAllCollectionCallAsFunction); + DECLARE_CALLBACK(HTMLSelectElementRemove); DECLARE_CALLBACK(HTMLOptionsCollectionRemove); @@ -319,6 +364,46 @@ namespace WebCore { DECLARE_CALLBACK(CanvasRenderingContext2DStrokeText); DECLARE_CALLBACK(CanvasRenderingContext2DPutImageData); +#if ENABLE(3D_CANVAS) + DECLARE_CALLBACK(WebGLRenderingContextBufferData); + DECLARE_CALLBACK(WebGLRenderingContextBufferSubData); + DECLARE_CALLBACK(WebGLRenderingContextGetBufferParameter); + DECLARE_CALLBACK(WebGLRenderingContextGetFramebufferAttachmentParameter); + DECLARE_CALLBACK(WebGLRenderingContextGetParameter); + DECLARE_CALLBACK(WebGLRenderingContextGetProgramParameter); + DECLARE_CALLBACK(WebGLRenderingContextGetRenderbufferParameter); + DECLARE_CALLBACK(WebGLRenderingContextGetShaderParameter); + DECLARE_CALLBACK(WebGLRenderingContextGetTexParameter); + DECLARE_CALLBACK(WebGLRenderingContextGetUniform); + DECLARE_CALLBACK(WebGLRenderingContextGetVertexAttrib); + DECLARE_CALLBACK(WebGLRenderingContextTexImage2D); + DECLARE_CALLBACK(WebGLRenderingContextTexSubImage2D); + DECLARE_CALLBACK(WebGLRenderingContextUniform1fv); + DECLARE_CALLBACK(WebGLRenderingContextUniform1iv); + DECLARE_CALLBACK(WebGLRenderingContextUniform2fv); + DECLARE_CALLBACK(WebGLRenderingContextUniform2iv); + DECLARE_CALLBACK(WebGLRenderingContextUniform3fv); + DECLARE_CALLBACK(WebGLRenderingContextUniform3iv); + DECLARE_CALLBACK(WebGLRenderingContextUniform4fv); + DECLARE_CALLBACK(WebGLRenderingContextUniform4iv); + DECLARE_CALLBACK(WebGLRenderingContextUniformMatrix2fv); + DECLARE_CALLBACK(WebGLRenderingContextUniformMatrix3fv); + DECLARE_CALLBACK(WebGLRenderingContextUniformMatrix4fv); + DECLARE_CALLBACK(WebGLRenderingContextVertexAttrib1fv); + DECLARE_CALLBACK(WebGLRenderingContextVertexAttrib2fv); + DECLARE_CALLBACK(WebGLRenderingContextVertexAttrib3fv); + DECLARE_CALLBACK(WebGLRenderingContextVertexAttrib4fv); + + DECLARE_CALLBACK(WebGLArrayBufferConstructor); + DECLARE_CALLBACK(WebGLByteArrayConstructor); + DECLARE_CALLBACK(WebGLFloatArrayConstructor); + DECLARE_CALLBACK(WebGLIntArrayConstructor); + DECLARE_CALLBACK(WebGLShortArrayConstructor); + DECLARE_CALLBACK(WebGLUnsignedByteArrayConstructor); + DECLARE_CALLBACK(WebGLUnsignedIntArrayConstructor); + DECLARE_CALLBACK(WebGLUnsignedShortArrayConstructor); +#endif + DECLARE_PROPERTY_ACCESSOR_GETTER(ClipboardTypes); DECLARE_CALLBACK(ClipboardClearData); DECLARE_CALLBACK(ClipboardGetData); @@ -332,6 +417,9 @@ namespace WebCore { DECLARE_CALLBACK(ElementSetAttributeNS); DECLARE_CALLBACK(ElementSetAttributeNodeNS); + DECLARE_CALLBACK(HistoryPushState); + DECLARE_CALLBACK(HistoryReplaceState); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationProtocol); DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHost); DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHostname); @@ -348,7 +436,6 @@ namespace WebCore { DECLARE_CALLBACK(LocationReload); DECLARE_CALLBACK(LocationToString); DECLARE_CALLBACK(LocationValueOf); - DECLARE_CALLBACK(NodeAddEventListener); DECLARE_CALLBACK(NodeRemoveEventListener); DECLARE_CALLBACK(NodeInsertBefore); @@ -394,22 +481,25 @@ namespace WebCore { DECLARE_CALLBACK(TreeWalkerNextSibling); DECLARE_CALLBACK(TreeWalkerPreviousSibling); - DECLARE_CALLBACK(InspectorBackendProfiles); - DECLARE_CALLBACK(InspectorBackendHighlightDOMNode); - DECLARE_CALLBACK(InspectorBackendAddResourceSourceToFrame); - DECLARE_CALLBACK(InspectorBackendAddSourceToFrame); - DECLARE_CALLBACK(InspectorBackendSearch); - DECLARE_CALLBACK(InspectorBackendSetting); - DECLARE_CALLBACK(InspectorBackendInspectedWindow); - DECLARE_CALLBACK(InspectorBackendSetSetting); - DECLARE_CALLBACK(InspectorBackendCurrentCallFrame); - DECLARE_CALLBACK(InspectorBackendDebuggerEnabled); - DECLARE_CALLBACK(InspectorBackendPauseOnExceptions); - DECLARE_CALLBACK(InspectorBackendProfilerEnabled); + DECLARE_CALLBACK(InjectedScriptHostInspectedWindow); + DECLARE_CALLBACK(InjectedScriptHostNodeForId); + DECLARE_CALLBACK(InjectedScriptHostWrapObject); + DECLARE_CALLBACK(InjectedScriptHostUnwrapObject); + DECLARE_CALLBACK(InjectedScriptHostPushNodePathToFrontend); + DECLARE_CALLBACK(InjectedScriptHostWrapCallback); #if ENABLE(DATABASE) - DECLARE_CALLBACK(InspectorBackendDatabaseTableNames); + DECLARE_CALLBACK(InjectedScriptHostSelectDatabase); + DECLARE_CALLBACK(InjectedScriptHostDatabaseForId); +#endif +#if ENABLE(DOM_STORAGE) + DECLARE_CALLBACK(InjectedScriptHostSelectDOMStorage); #endif - DECLARE_CALLBACK(InspectorBackendWrapCallback); + + DECLARE_CALLBACK(InspectorFrontendHostSearch); + DECLARE_CALLBACK(InspectorFrontendHostShowContextMenu); + + DECLARE_CALLBACK(ConsoleProfile); + DECLARE_CALLBACK(ConsoleProfileEnd); DECLARE_CALLBACK(NodeIteratorNextNode); DECLARE_CALLBACK(NodeIteratorPreviousNode); @@ -443,31 +533,78 @@ namespace WebCore { DECLARE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection); DECLARE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection); DECLARE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection); + DECLARE_NAMED_PROPERTY_GETTER(HTMLAllCollection); DECLARE_NAMED_PROPERTY_GETTER(HTMLCollection); - DECLARE_INDEXED_PROPERTY_GETTER(CanvasPixelArray); - DECLARE_INDEXED_PROPERTY_SETTER(CanvasPixelArray); +#if ENABLE(3D_CANVAS) + DECLARE_CALLBACK(WebGLByteArrayGet); + DECLARE_CALLBACK(WebGLByteArraySet); + DECLARE_INDEXED_PROPERTY_GETTER(WebGLByteArray); + DECLARE_INDEXED_PROPERTY_SETTER(WebGLByteArray); + + DECLARE_CALLBACK(WebGLFloatArrayGet); + DECLARE_CALLBACK(WebGLFloatArraySet); + DECLARE_INDEXED_PROPERTY_GETTER(WebGLFloatArray); + DECLARE_INDEXED_PROPERTY_SETTER(WebGLFloatArray); + + DECLARE_CALLBACK(WebGLIntArrayGet); + DECLARE_CALLBACK(WebGLIntArraySet); + DECLARE_INDEXED_PROPERTY_GETTER(WebGLIntArray); + DECLARE_INDEXED_PROPERTY_SETTER(WebGLIntArray); + + DECLARE_CALLBACK(WebGLShortArrayGet); + DECLARE_CALLBACK(WebGLShortArraySet); + DECLARE_INDEXED_PROPERTY_GETTER(WebGLShortArray); + DECLARE_INDEXED_PROPERTY_SETTER(WebGLShortArray); + + DECLARE_CALLBACK(WebGLUnsignedByteArrayGet); + DECLARE_CALLBACK(WebGLUnsignedByteArraySet); + DECLARE_INDEXED_PROPERTY_GETTER(WebGLUnsignedByteArray); + DECLARE_INDEXED_PROPERTY_SETTER(WebGLUnsignedByteArray); + + DECLARE_CALLBACK(WebGLUnsignedIntArrayGet); + DECLARE_CALLBACK(WebGLUnsignedIntArraySet); + DECLARE_INDEXED_PROPERTY_GETTER(WebGLUnsignedIntArray); + DECLARE_INDEXED_PROPERTY_SETTER(WebGLUnsignedIntArray); + + DECLARE_CALLBACK(WebGLUnsignedShortArrayGet); + DECLARE_CALLBACK(WebGLUnsignedShortArraySet); + DECLARE_INDEXED_PROPERTY_GETTER(WebGLUnsignedShortArray); + DECLARE_INDEXED_PROPERTY_SETTER(WebGLUnsignedShortArray); +#endif + + DECLARE_PROPERTY_ACCESSOR_GETTER(MessageEventPorts); + DECLARE_CALLBACK(MessageEventInitMessageEvent); DECLARE_PROPERTY_ACCESSOR(MessagePortOnmessage); DECLARE_PROPERTY_ACCESSOR(MessagePortOnclose); - DECLARE_CALLBACK(MessagePortStartConversation); DECLARE_CALLBACK(MessagePortAddEventListener); + DECLARE_CALLBACK(MessagePortPostMessage); DECLARE_CALLBACK(MessagePortRemoveEventListener); + DECLARE_CALLBACK(MessagePortStartConversation); DECLARE_CALLBACK(DatabaseChangeVersion); DECLARE_CALLBACK(DatabaseTransaction); + DECLARE_CALLBACK(DatabaseReadTransaction); DECLARE_CALLBACK(SQLTransactionExecuteSql); DECLARE_CALLBACK(SQLResultSetRowListItem); DECLARE_INDEXED_PROPERTY_GETTER(ClientRectList); - + DECLARE_INDEXED_PROPERTY_GETTER(FileList); + #if ENABLE(DATAGRID) DECLARE_PROPERTY_ACCESSOR(HTMLDataGridElementDataSource); DECLARE_INDEXED_PROPERTY_GETTER(DataGridColumnList); DECLARE_NAMED_PROPERTY_GETTER(DataGridColumnList); -#endif +#endif + +#if ENABLE(DATABASE) + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowOpenDatabase); +#endif #if ENABLE(DOM_STORAGE) + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowLocalStorage); + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowSessionStorage); DECLARE_INDEXED_PROPERTY_GETTER(Storage); DECLARE_INDEXED_PROPERTY_SETTER(Storage); DECLARE_INDEXED_PROPERTY_DELETER(Storage); @@ -480,6 +617,7 @@ namespace WebCore { #if ENABLE(SVG) DECLARE_PROPERTY_ACCESSOR_GETTER(SVGLengthValue); DECLARE_CALLBACK(SVGLengthConvertToSpecifiedUnits); + DECLARE_CALLBACK(SVGMatrixMultiply); DECLARE_CALLBACK(SVGMatrixInverse); DECLARE_CALLBACK(SVGMatrixRotateFromVector); DECLARE_CALLBACK(SVGElementInstanceAddEventListener); @@ -496,8 +634,10 @@ namespace WebCore { DECLARE_CALLBACK(AbstractWorkerRemoveEventListener); DECLARE_PROPERTY_ACCESSOR(DedicatedWorkerContextOnmessage); + DECLARE_CALLBACK(DedicatedWorkerContextPostMessage); DECLARE_PROPERTY_ACCESSOR(WorkerOnmessage); + DECLARE_CALLBACK(WorkerPostMessage); DECLARE_CALLBACK(WorkerConstructor); DECLARE_PROPERTY_ACCESSOR_GETTER(WorkerContextSelf); @@ -509,9 +649,24 @@ namespace WebCore { DECLARE_CALLBACK(WorkerContextClearInterval); DECLARE_CALLBACK(WorkerContextAddEventListener); DECLARE_CALLBACK(WorkerContextRemoveEventListener); + +#if ENABLE(NOTIFICATIONS) + DECLARE_ACCESSOR_RUNTIME_ENABLER(WorkerContextWebkitNotifications); #endif +#endif // ENABLE(WORKERS) + +#if ENABLE(NOTIFICATIONS) + DECLARE_CALLBACK(NotificationCenterRequestPermission); + DECLARE_CALLBACK(NotificationCenterCreateNotification); + DECLARE_CALLBACK(NotificationCenterCreateHTMLNotification); + + DECLARE_CALLBACK(NotificationAddEventListener); + DECLARE_CALLBACK(NotificationRemoveEventListener); + DECLARE_PROPERTY_ACCESSOR(NotificationEventHandler); +#endif // ENABLE(NOTIFICATIONS) #if ENABLE(OFFLINE_WEB_APPLICATIONS) + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowApplicationCache); DECLARE_PROPERTY_ACCESSOR(DOMApplicationCacheEventHandler); DECLARE_CALLBACK(DOMApplicationCacheAddEventListener); DECLARE_CALLBACK(DOMApplicationCacheRemoveEventListener); @@ -519,6 +674,23 @@ namespace WebCore { #if ENABLE(SHARED_WORKERS) DECLARE_CALLBACK(SharedWorkerConstructor); + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowSharedWorker); +#endif + +#if ENABLE(NOTIFICATIONS) + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowWebkitNotifications); +#endif + +#if ENABLE(WEB_SOCKETS) + DECLARE_PROPERTY_ACCESSOR(WebSocketOnopen); + DECLARE_PROPERTY_ACCESSOR(WebSocketOnmessage); + DECLARE_PROPERTY_ACCESSOR(WebSocketOnclose); + DECLARE_CALLBACK(WebSocketConstructor); + DECLARE_CALLBACK(WebSocketAddEventListener); + DECLARE_CALLBACK(WebSocketRemoveEventListener); + DECLARE_CALLBACK(WebSocketSend); + DECLARE_CALLBACK(WebSocketClose); + DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowWebSocket); #endif DECLARE_CALLBACK(GeolocationGetCurrentPosition); diff --git a/WebCore/bindings/v8/custom/V8CustomEventListener.cpp b/WebCore/bindings/v8/custom/V8CustomEventListener.cpp index 305da8d..24d752f 100644 --- a/WebCore/bindings/v8/custom/V8CustomEventListener.cpp +++ b/WebCore/bindings/v8/custom/V8CustomEventListener.cpp @@ -35,37 +35,25 @@ namespace WebCore { -V8EventListener::V8EventListener(Frame* frame, v8::Local<v8::Object> listener, bool isAttribute) - : V8AbstractEventListener(frame, isAttribute) +V8EventListener::V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, const WorldContextHandle& worldContext) + : V8AbstractEventListener(isAttribute, worldContext) { - m_listener = v8::Persistent<v8::Object>::New(listener); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener); -#endif + setListenerObject(listener); } -V8EventListener::~V8EventListener() +v8::Local<v8::Function> V8EventListener::getListenerFunction(ScriptExecutionContext* context) { - if (m_frame) { - V8Proxy* proxy = V8Proxy::retrieve(m_frame); - if (proxy) - proxy->eventListeners()->remove(this); - } - - disposeListenerObject(); -} + v8::Local<v8::Object> listener = getListenerObject(context); -v8::Local<v8::Function> V8EventListener::getListenerFunction() -{ // Has the listener been disposed? - if (m_listener.IsEmpty()) + if (listener.IsEmpty()) return v8::Local<v8::Function>(); - if (m_listener->IsFunction()) - return v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener)); + if (listener->IsFunction()) + return v8::Local<v8::Function>::Cast(listener); - if (m_listener->IsObject()) { - v8::Local<v8::Value> property = m_listener->Get(v8::String::NewSymbol("handleEvent")); + if (listener->IsObject()) { + v8::Local<v8::Value> property = listener->Get(v8::String::NewSymbol("handleEvent")); if (property->IsFunction()) return v8::Local<v8::Function>::Cast(property); } @@ -73,19 +61,20 @@ v8::Local<v8::Function> V8EventListener::getListenerFunction() return v8::Local<v8::Function>(); } -v8::Local<v8::Value> V8EventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event, bool isWindowEvent) +v8::Local<v8::Value> V8EventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Function> handlerFunction = getListenerFunction(); - v8::Local<v8::Object> receiver = getReceiverObject(event, isWindowEvent); + + v8::Local<v8::Function> handlerFunction = getListenerFunction(context); + v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); v8::Handle<v8::Value> parameters[1] = { jsEvent }; - V8Proxy* proxy = V8Proxy::retrieve(m_frame); - if (!proxy) - return v8::Local<v8::Value>(); - return proxy->callFunction(handlerFunction, receiver, 1, parameters); + if (V8Proxy* proxy = V8Proxy::retrieve(context)) + return proxy->callFunction(handlerFunction, receiver, 1, parameters); + + return v8::Local<v8::Value>(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomEventListener.h b/WebCore/bindings/v8/custom/V8CustomEventListener.h index 20adf99..f9d5385 100644 --- a/WebCore/bindings/v8/custom/V8CustomEventListener.h +++ b/WebCore/bindings/v8/custom/V8CustomEventListener.h @@ -44,23 +44,19 @@ namespace WebCore { // that can handle the event. class V8EventListener : public V8AbstractEventListener { public: - static PassRefPtr<V8EventListener> create(Frame* frame, v8::Local<v8::Object> listener, bool isAttribute) + static PassRefPtr<V8EventListener> create(v8::Local<v8::Object> listener, bool isAttribute, const WorldContextHandle& worldContext) { - return adoptRef(new V8EventListener(frame, listener, isAttribute)); + return adoptRef(new V8EventListener(listener, isAttribute, worldContext)); } - // Detach the listener from its owner frame. - void disconnectFrame() { m_frame = 0; } - protected: - V8EventListener(Frame*, v8::Local<v8::Object> listener, bool isAttribute); - virtual ~V8EventListener(); - v8::Local<v8::Function> getListenerFunction(); + V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, const WorldContextHandle& worldContext); + + v8::Local<v8::Function> getListenerFunction(ScriptExecutionContext*); private: - virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*, bool isWindowEvent); - virtual bool virtualisAttribute() const { return m_isAttribute; } - }; + virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); + }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomPositionCallback.cpp b/WebCore/bindings/v8/custom/V8CustomPositionCallback.cpp index 4f2fe0e..5e9a8f2 100644 --- a/WebCore/bindings/v8/custom/V8CustomPositionCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomPositionCallback.cpp @@ -1,29 +1,24 @@ /* - * Copyright (c) 2009, Google Inc. All rights reserved. + * Copyright 2009, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -49,7 +44,6 @@ V8CustomPositionCallback::~V8CustomPositionCallback() void V8CustomPositionCallback::handleEvent(Geoposition* position) { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); diff --git a/WebCore/bindings/v8/custom/V8CustomPositionCallback.h b/WebCore/bindings/v8/custom/V8CustomPositionCallback.h index 06be83b..d2290ee 100644 --- a/WebCore/bindings/v8/custom/V8CustomPositionCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomPositionCallback.h @@ -1,29 +1,24 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright 2009, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ diff --git a/WebCore/bindings/v8/custom/V8CustomPositionErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomPositionErrorCallback.cpp index e446d85..117f374 100644 --- a/WebCore/bindings/v8/custom/V8CustomPositionErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomPositionErrorCallback.cpp @@ -1,29 +1,24 @@ /* - * Copyright (c) 2009, Google Inc. All rights reserved. + * Copyright 2009, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -49,7 +44,6 @@ V8CustomPositionErrorCallback::~V8CustomPositionErrorCallback() void V8CustomPositionErrorCallback::handleEvent(PositionError* error) { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); diff --git a/WebCore/bindings/v8/custom/V8CustomPositionErrorCallback.h b/WebCore/bindings/v8/custom/V8CustomPositionErrorCallback.h index 703b7b2..aaf56a7 100644 --- a/WebCore/bindings/v8/custom/V8CustomPositionErrorCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomPositionErrorCallback.h @@ -1,29 +1,24 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright 2009, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp index 2abdb15..64abdc4 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp @@ -52,7 +52,6 @@ V8CustomSQLStatementCallback::~V8CustomSQLStatementCallback() void V8CustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index efab455..1af3562 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -52,7 +52,6 @@ V8CustomSQLStatementErrorCallback::~V8CustomSQLStatementErrorCallback() bool V8CustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLError* error) { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp index 704115e..2cef6b3 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp @@ -53,7 +53,6 @@ V8CustomSQLTransactionCallback::~V8CustomSQLTransactionCallback() void V8CustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bool& raisedException) { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp index f30467c..1a0939d 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp @@ -52,7 +52,6 @@ V8CustomSQLTransactionErrorCallback::~V8CustomSQLTransactionErrorCallback() void V8CustomSQLTransactionErrorCallback::handleEvent(SQLError* error) { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp index b538b33..94cb104 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp @@ -49,7 +49,6 @@ V8CustomVoidCallback::~V8CustomVoidCallback() void V8CustomVoidCallback::handleEvent() { - LOCK_V8; v8::HandleScope handleScope; v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp index 3341924..e45cba0 100644 --- a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp @@ -38,13 +38,14 @@ namespace WebCore { -PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver) +PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(V8Proxy* proxy, v8::Handle<v8::Object> resolver) { - return adoptRef(new V8CustomXPathNSResolver(resolver)); + return adoptRef(new V8CustomXPathNSResolver(proxy, resolver)); } -V8CustomXPathNSResolver::V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver) - : m_resolver(resolver) +V8CustomXPathNSResolver::V8CustomXPathNSResolver(V8Proxy* proxy, v8::Handle<v8::Object> resolver) + : m_proxy(proxy) + , m_resolver(resolver) { } @@ -54,6 +55,14 @@ V8CustomXPathNSResolver::~V8CustomXPathNSResolver() String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) { + V8Proxy* proxy = m_proxy; + + if (!proxy) { + proxy = V8Proxy::retrieve(); + if (!proxy) + return String(); + } + v8::Handle<v8::Function> lookupNamespaceURIFunc; v8::Handle<v8::String> lookupNamespaceURIName = v8::String::New("lookupNamespaceURI"); @@ -65,7 +74,7 @@ String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) } if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { - Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + Frame* frame = proxy->frame(); logInfo(frame, "XPathNSResolver does not have a lookupNamespaceURI method.", String()); return String(); } @@ -78,7 +87,6 @@ String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) v8::Handle<v8::Value> argv[argc] = { v8String(prefix) }; v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Handle<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; - V8Proxy* proxy = V8Proxy::retrieve(); v8::Handle<v8::Value> retval = proxy->callFunction(function, m_resolver, argc, argv); // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NAMESPACE_ERR. diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h index f1dc65c..15ac27d 100644 --- a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h @@ -42,17 +42,22 @@ namespace WebCore { class String; +class V8Proxy; +// V8CustomXPathNSResolver does not create a persistent handle to the +// given resolver object. So the lifetime of V8CustomXPathNSResolver +// must not exceed the lifetime of the passed handle. class V8CustomXPathNSResolver : public XPathNSResolver { public: - static PassRefPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver); + static PassRefPtr<V8CustomXPathNSResolver> create(V8Proxy* proxy, v8::Handle<v8::Object> resolver); virtual ~V8CustomXPathNSResolver(); virtual String lookupNamespaceURI(const String& prefix); private: - V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver); + V8CustomXPathNSResolver(V8Proxy* proxy, v8::Handle<v8::Object> resolver); + V8Proxy* m_proxy; v8::Handle<v8::Object> m_resolver; // Handle to resolver object. }; diff --git a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp index 7a3bfe6..134de95 100644 --- a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp @@ -37,77 +37,19 @@ #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Document.h" -#include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContextExecutionProxy.h" namespace WebCore { -static const bool kFindOnly = true; -static const bool kFindOrCreate = false; - -static PassRefPtr<EventListener> argumentToEventListener(DOMApplicationCache* appcache, v8::Local<v8::Value> value, bool findOnly) -{ - V8Proxy* proxy = V8Proxy::retrieve(appcache->scriptExecutionContext()); - if (proxy) - return findOnly ? proxy->objectListeners()->findWrapper(value, false) - : proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); - return 0; -} - -static v8::Local<v8::Object> eventListenerToV8Object(EventListener* listener) -{ - return (static_cast<V8ObjectEventListener*>(listener))->getListenerObject(); -} - -static inline ApplicationCacheHost::EventID toEventID(v8::Local<v8::String> value) -{ - String key = toWebCoreString(value); - ASSERT(key.startsWith("on")); - return DOMApplicationCache::toEventID(key.substring(2)); -} - -// Handles appcache.onfooevent attribute getting -ACCESSOR_GETTER(DOMApplicationCacheEventHandler) -{ - INC_STATS("DOMApplicationCache.onevent_getter"); - DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); - EventListener* listener = appcache->getAttributeEventListener(toEventID(name)); - if (!listener) - return v8::Null(); - return eventListenerToV8Object(listener); -} - -// Handles appcache.onfooevent attribute setting -ACCESSOR_SETTER(DOMApplicationCacheEventHandler) -{ - INC_STATS("DOMApplicationCache.onevent_setter"); - DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); - ApplicationCacheHost::EventID eventType = toEventID(name); - - if (EventListener* oldListener = appcache->getAttributeEventListener(eventType)) { - v8::Local<v8::Object> object = eventListenerToV8Object(oldListener); - removeHiddenDependency(info.Holder(), object, V8Custom::kDOMApplicationCacheCacheIndex); - appcache->clearAttributeEventListener(eventType); - } - - if (value->IsFunction()) { - RefPtr<EventListener> newListener = argumentToEventListener(appcache, value, kFindOrCreate); - if (newListener) { - createHiddenDependency(info.Holder(), value, V8Custom::kDOMApplicationCacheCacheIndex); - appcache->setAttributeEventListener(eventType, newListener); - } - } -} - // Handles appcache.addEventListner(name, func, capture) method calls CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener) { INC_STATS("DOMApplicationCache.addEventListener()"); DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); - RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOrCreate); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOrCreate); if (listener) { createHiddenDependency(args.Holder(), args[1], V8Custom::kDOMApplicationCacheCacheIndex); String eventType = toWebCoreString(args[0]); @@ -123,7 +65,7 @@ CALLBACK_FUNC_DECL(DOMApplicationCacheRemoveEventListener) INC_STATS("DOMApplicationCache.removeEventListener()"); DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); - RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOnly); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOnly); if (listener) { removeHiddenDependency(args.Holder(), args[1], V8Custom::kDOMApplicationCacheCacheIndex); String eventType = toWebCoreString(args[0]); diff --git a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp index 7d0b9e6..46c33b9 100644 --- a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp @@ -34,6 +34,7 @@ #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8CustomEventListener.h" +#include "V8MessagePortCustom.h" #include "V8Proxy.h" #include "V8Utilities.h" @@ -44,11 +45,19 @@ #include "FrameLoadRequest.h" #include "FrameView.h" #include "HTMLCollection.h" +#include "MediaPlayer.h" #include "Page.h" #include "PlatformScreen.h" +#include "RuntimeEnabledFeatures.h" #include "ScheduledAction.h" #include "ScriptSourceCode.h" +#include "SerializedScriptValue.h" #include "Settings.h" +#include "SharedWorkerRepository.h" +#include "Storage.h" +#if ENABLE(WEB_SOCKETS) +#include "WebSocket.h" +#endif #include "WindowFeatures.h" // Horizontal and vertical offset, from the parent content area, around newly @@ -64,32 +73,44 @@ v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args, if (argumentCount < 1) return v8::Undefined(); - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - - if (!imp->frame()) - return v8::Undefined(); - - if (!V8Proxy::canAccessFrame(imp->frame(), true)) - return v8::Undefined(); + v8::Handle<v8::Value> function = args[0]; - ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->frame()->document()); + WebCore::String functionString; + if (!function->IsFunction()) { + if (function->IsString()) + functionString = toWebCoreString(function); + else { + v8::Handle<v8::Value> v8String = function->ToString(); - v8::Handle<v8::Value> function = args[0]; + // Bail out if string conversion failed. + if (v8String.IsEmpty()) + return v8::Undefined(); - int32_t timeout = 0; - if (argumentCount >= 2) - timeout = args[1]->Int32Value(); + functionString = toWebCoreString(v8String); + } - int id; - if (function->IsString()) { // Don't allow setting timeouts to run empty functions! // (Bug 1009597) - WebCore::String functionString = toWebCoreString(function); if (functionString.length() == 0) return v8::Undefined(); + } - id = DOMTimer::install(scriptContext, new ScheduledAction(functionString), timeout, singleShot); - } else if (function->IsFunction()) { + int32_t timeout = 0; + if (argumentCount >= 2) + timeout = args[1]->Int32Value(); + + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + + if (!V8Proxy::canAccessFrame(imp->frame(), true)) + return v8::Undefined(); + + ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->document()); + + if (!scriptContext) + return v8::Undefined(); + + int id; + if (function->IsFunction()) { int paramCount = argumentCount >= 2 ? argumentCount - 2 : 0; v8::Local<v8::Value>* params = 0; if (paramCount > 0) { @@ -100,14 +121,14 @@ v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args, } // params is passed to action, and released in action's destructor - ScheduledAction* action = new ScheduledAction(v8::Handle<v8::Function>::Cast(function), paramCount, params); + ScheduledAction* action = new ScheduledAction(V8Proxy::context(imp->frame()), v8::Handle<v8::Function>::Cast(function), paramCount, params); delete[] params; id = DOMTimer::install(scriptContext, action, timeout, singleShot); - } else - // FIXME(fqian): what's the right return value if failed. - return v8::Undefined(); + } else { + id = DOMTimer::install(scriptContext, new ScheduledAction(V8Proxy::context(imp->frame()), functionString), timeout, singleShot); + } return v8::Integer::New(id); } @@ -145,14 +166,43 @@ static v8::Handle<v8::Value> convertBase64(const String& str, bool encode) ACCESSOR_GETTER(DOMWindowEvent) { + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + if (holder.IsEmpty()) + return v8::Undefined(); + + Frame* frame = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder)->frame(); + if (!V8Proxy::canAccessFrame(frame, true)) + return v8::Undefined(); + + v8::Local<v8::Context> context = V8Proxy::context(frame); + if (context.IsEmpty()) + return v8::Undefined(); + v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event"); - v8::Local<v8::Context> context = v8::Context::GetCurrent(); v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol); if (jsEvent.IsEmpty()) return v8::Undefined(); return jsEvent; } +ACCESSOR_SETTER(DOMWindowEvent) +{ + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + if (holder.IsEmpty()) + return; + + Frame* frame = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder)->frame(); + if (!V8Proxy::canAccessFrame(frame, true)) + return; + + v8::Local<v8::Context> context = V8Proxy::context(frame); + if (context.IsEmpty()) + return; + + v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event"); + context->Global()->SetHiddenValue(eventSymbol, value); +} + ACCESSOR_GETTER(DOMWindowCrypto) { // FIXME: Implement me. @@ -161,11 +211,7 @@ ACCESSOR_GETTER(DOMWindowCrypto) ACCESSOR_SETTER(DOMWindowLocation) { - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); - if (holder.IsEmpty()) - return; - - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); WindowSetLocation(imp, toWebCoreString(value)); } @@ -194,18 +240,114 @@ ACCESSOR_SETTER(DOMWindowOpener) info.This()->Set(name, value); } +#if ENABLE(VIDEO) + +ACCESSOR_GETTER(DOMWindowAudio) +{ + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + return V8DOMWrapper::getConstructor(V8ClassIndex::AUDIO, window); +} + +ACCESSOR_RUNTIME_ENABLER(DOMWindowAudio) +{ + return MediaPlayer::isAvailable(); +} + +ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLMediaElement) +{ + return MediaPlayer::isAvailable(); +} + +ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLAudioElement) +{ + return MediaPlayer::isAvailable(); +} + +ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLVideoElement) +{ + return MediaPlayer::isAvailable(); +} + +ACCESSOR_RUNTIME_ENABLER(DOMWindowMediaError) +{ + return MediaPlayer::isAvailable(); +} + +#endif + +#if ENABLE(SHARED_WORKERS) +ACCESSOR_RUNTIME_ENABLER(DOMWindowSharedWorker) +{ + return SharedWorkerRepository::isAvailable(); +} +#endif + +#if ENABLE(WEB_SOCKETS) +ACCESSOR_RUNTIME_ENABLER(DOMWindowWebSocket) +{ + return WebSocket::isAvailable(); +} +#endif + +#if ENABLE(DATABASE) +ACCESSOR_RUNTIME_ENABLER(DOMWindowOpenDatabase) +{ + return WebCore::RuntimeEnabledFeatures::databaseEnabled(); +} +#endif + +#if ENABLE(DOM_STORAGE) +ACCESSOR_RUNTIME_ENABLER(DOMWindowLocalStorage) +{ + return RuntimeEnabledFeatures::localStorageEnabled(); +} + +ACCESSOR_RUNTIME_ENABLER(DOMWindowSessionStorage) +{ + return RuntimeEnabledFeatures::sessionStorageEnabled(); +} +#endif + +#if ENABLE(NOTIFICATIONS) +ACCESSOR_RUNTIME_ENABLER(DOMWindowWebkitNotifications) +{ + return RuntimeEnabledFeatures::notificationsEnabled(); +} +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +ACCESSOR_RUNTIME_ENABLER(DOMWindowApplicationCache) +{ + return RuntimeEnabledFeatures::applicationCacheEnabled(); +} +#endif + +ACCESSOR_GETTER(DOMWindowImage) +{ + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + return V8DOMWrapper::getConstructor(V8ClassIndex::IMAGE, window); +} + +ACCESSOR_GETTER(DOMWindowOption) +{ + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + return V8DOMWrapper::getConstructor(V8ClassIndex::OPTION, window); +} + CALLBACK_FUNC_DECL(DOMWindowAddEventListener) { INC_STATS("DOM.DOMWindow.addEventListener()"); + + String eventType = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); - if (!imp->frame()) - return v8::Undefined(); // DOMWindow could be disconnected from the frame - - Document* doc = imp->frame()->document(); + Document* doc = imp->document(); + if (!doc) return v8::Undefined(); @@ -214,12 +356,11 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener) if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(proxy, args[1], false, ListenerFindOrCreate); if (listener) { - String eventType = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); imp->addEventListener(eventType, listener, useCapture); + createHiddenDependency(args.Holder(), args[1], V8Custom::kDOMWindowEventListenerCacheIndex); } return v8::Undefined(); @@ -229,15 +370,17 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener) CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) { INC_STATS("DOM.DOMWindow.removeEventListener()"); + + String eventType = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); - if (!imp->frame()) - return v8::Undefined(); + Document* doc = imp->document(); - Document* doc = imp->frame()->document(); if (!doc) return v8::Undefined(); @@ -245,12 +388,11 @@ CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(proxy, args[1], false, ListenerFindOnly); if (listener) { - String eventType = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); imp->removeEventListener(eventType, listener.get(), useCapture); + removeHiddenDependency(args.Holder(), args[1], V8Custom::kDOMWindowEventListenerCacheIndex); } return v8::Undefined(); @@ -265,8 +407,8 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) ASSERT(source->frame()); v8::TryCatch tryCatch; - String message = toWebCoreString(args[0]); - MessagePort* port = 0; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0])); + MessagePortArray portArray; String targetOrigin; // This function has variable arguments and can either be: @@ -274,8 +416,8 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) // or // postMessage(message, targetOrigin); if (args.Length() > 2) { - if (V8DOMWrapper::isWrapperOfType(args[1], V8ClassIndex::MESSAGEPORT)) - port = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, v8::Handle<v8::Object>::Cast(args[1])); + if (!getMessagePortArray(args[1], portArray)) + return v8::Undefined(); targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[2]); } else { targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[1]); @@ -285,16 +427,18 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) return v8::Undefined(); ExceptionCode ec = 0; - window->postMessage(message, port, targetOrigin, source, ec); - if (ec) - V8Proxy::setDOMException(ec); - - return v8::Undefined(); + window->postMessage(message.release(), &portArray, targetOrigin, source, ec); + return throwError(ec); } CALLBACK_FUNC_DECL(DOMWindowAtob) { INC_STATS("DOM.DOMWindow.atob()"); + + if (args[0]->IsNull()) + return v8String(""); + String str = toWebCoreString(args[0]); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); if (!V8Proxy::canAccessFrame(imp->frame(), true)) @@ -303,16 +447,17 @@ CALLBACK_FUNC_DECL(DOMWindowAtob) if (args.Length() < 1) return throwError("Not enough arguments", V8Proxy::SyntaxError); - if (args[0]->IsNull()) - return v8String(""); - - String str = toWebCoreString(args[0]); return convertBase64(str, false); } CALLBACK_FUNC_DECL(DOMWindowBtoa) { INC_STATS("DOM.DOMWindow.btoa()"); + + if (args[0]->IsNull()) + return v8String(""); + String str = toWebCoreString(args[0]); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); if (!V8Proxy::canAccessFrame(imp->frame(), true)) @@ -321,10 +466,6 @@ CALLBACK_FUNC_DECL(DOMWindowBtoa) if (args.Length() < 1) return throwError("Not enough arguments", V8Proxy::SyntaxError); - if (args[0]->IsNull()) - return v8String(""); - - String str = toWebCoreString(args[0]); return convertBase64(str, true); } @@ -335,7 +476,10 @@ CALLBACK_FUNC_DECL(DOMWindowBtoa) CALLBACK_FUNC_DECL(DOMWindowToString) { INC_STATS("DOM.DOMWindow.toString()"); - return args.This()->ObjectProtoToString(); + v8::Handle<v8::Object> domWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, args.This()); + if (domWrapper.IsEmpty()) + return args.This()->ObjectProtoToString(); + return domWrapper->ObjectProtoToString(); } CALLBACK_FUNC_DECL(DOMWindowNOP) @@ -344,84 +488,6 @@ CALLBACK_FUNC_DECL(DOMWindowNOP) return v8::Undefined(); } -static String eventNameFromAttributeName(const String& name) -{ - ASSERT(name.startsWith("on")); - String eventType = name.substring(2); - - if (eventType.startsWith("w")) { - switch(eventType[eventType.length() - 1]) { - case 't': - eventType = "webkitAnimationStart"; - break; - case 'n': - eventType = "webkitAnimationIteration"; - break; - case 'd': - ASSERT(eventType.length() > 7); - if (eventType[7] == 'a') - eventType = "webkitAnimationEnd"; - else - eventType = "webkitTransitionEnd"; - break; - } - } - - return eventType; -} - -ACCESSOR_SETTER(DOMWindowEventHandler) -{ - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); - if (holder.IsEmpty()) - return; - - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); - if (!imp->frame()) - return; - - Document* doc = imp->frame()->document(); - if (!doc) - return; - - String key = toWebCoreString(name); - String eventType = eventNameFromAttributeName(key); - - if (value->IsNull()) { - // Clear the event listener - imp->clearAttributeEventListener(eventType); - } else { - V8Proxy* proxy = V8Proxy::retrieve(imp->frame()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), value, true); - if (listener) - imp->setAttributeEventListener(eventType, listener); - } -} - -ACCESSOR_GETTER(DOMWindowEventHandler) -{ - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); - if (holder.IsEmpty()) - return v8::Undefined(); - - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); - if (!imp->frame()) - return v8::Undefined(); - - Document* doc = imp->frame()->document(); - if (!doc) - return v8::Undefined(); - - String key = toWebCoreString(name); - String eventType = eventNameFromAttributeName(key); - - EventListener* listener = imp->getAttributeEventListener(eventType); - return V8DOMWrapper::convertEventListenerToV8Object(listener); -} - static bool canShowModalDialogNow(const Frame* frame) { // A frame can out live its page. See bug 1219613. @@ -484,6 +550,10 @@ static Frame* createWindow(Frame* callingFrame, ASSERT(callingFrame); ASSERT(enteredFrame); + // Sandboxed iframes cannot open new auxiliary browsing contexts. + if (callingFrame && callingFrame->loader()->isSandboxed(SandboxNavigation)) + return 0; + ResourceRequest request; // For whatever reason, Firefox uses the entered frame to determine @@ -512,7 +582,7 @@ static Frame* createWindow(Frame* callingFrame, return 0; newFrame->loader()->setOpener(openerFrame); - newFrame->loader()->setOpenedByDOM(); + newFrame->page()->setOpenedByDOM(); // Set dialog arguments on the global object of the new frame. if (!dialogArgs.IsEmpty()) { @@ -525,13 +595,13 @@ static Frame* createWindow(Frame* callingFrame, if (protocolIsJavaScript(url) || ScriptController::isSafeScript(newFrame)) { KURL completedUrl = - url.isEmpty() ? KURL("") : completeURL(url); + url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(url); bool userGesture = processingUserGesture(); if (created) newFrame->loader()->changeLocation(completedUrl, referrer, false, false, userGesture); else if (!url.isEmpty()) - newFrame->loader()->scheduleLocationChange(completedUrl.string(), referrer, false, userGesture); + newFrame->redirectScheduler()->scheduleLocationChange(completedUrl.string(), referrer, false, userGesture); } return newFrame; @@ -542,11 +612,16 @@ static Frame* createWindow(Frame* callingFrame, CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) { INC_STATS("DOM.DOMWindow.showModalDialog()"); + + String url = toWebCoreStringWithNullOrUndefinedCheck(args[0]); + v8::Local<v8::Value> dialogArgs = args[1]; + String featureArgs = toWebCoreStringWithNullOrUndefinedCheck(args[2]); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>( V8ClassIndex::DOMWINDOW, args.Holder()); Frame* frame = window->frame(); - if (!frame || !V8Proxy::canAccessFrame(frame, true)) + if (!V8Proxy::canAccessFrame(frame, true)) return v8::Undefined(); Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); @@ -560,10 +635,6 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) if (!canShowModalDialogNow(frame) || !allowPopUp()) return v8::Undefined(); - String url = toWebCoreStringWithNullOrUndefinedCheck(args[0]); - v8::Local<v8::Value> dialogArgs = args[1]; - String featureArgs = toWebCoreStringWithNullOrUndefinedCheck(args[2]); - const HashMap<String, String> features = parseModalDialogFeatures(featureArgs); const bool trusted = false; @@ -631,27 +702,29 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) CALLBACK_FUNC_DECL(DOMWindowOpen) { INC_STATS("DOM.DOMWindow.open()"); + + String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]); + AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1])); + DOMWindow* parent = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); Frame* frame = parent->frame(); - if (!frame || !V8Proxy::canAccessFrame(frame, true)) - return v8::Undefined(); - - Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); - if (!callingFrame) + if (!V8Proxy::canAccessFrame(frame, true)) return v8::Undefined(); Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); if (!enteredFrame) return v8::Undefined(); + Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); + // We may not have a calling context if we are invoked by a plugin via NPAPI. + if (!callingFrame) + callingFrame = enteredFrame; + Page* page = frame->page(); if (!page) return v8::Undefined(); - String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]); - AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1])); - // Because FrameTree::find() returns true for empty strings, we must check // for empty framenames. Otherwise, illegitimate window.open() calls with // no name will pass right through the popup blocker. @@ -687,7 +760,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) // the outgoingReferrer. We replicate that behavior here. String referrer = enteredFrame->loader()->outgoingReferrer(); - frame->loader()->scheduleLocationChange(completedUrl, referrer, false, userGesture); + frame->redirectScheduler()->scheduleLocationChange(completedUrl, referrer, false, userGesture); } return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); } @@ -756,11 +829,8 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) INDEXED_PROPERTY_GETTER(DOMWindow) { INC_STATS("DOM.DOMWindow.IndexedPropertyGetter"); - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); - if (holder.IsEmpty()) - return notHandledByInterceptor(); - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); if (!window) return notHandledByInterceptor(); @@ -780,11 +850,8 @@ NAMED_PROPERTY_GETTER(DOMWindow) { INC_STATS("DOM.DOMWindow.NamedPropertyGetter"); - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); - if (holder.IsEmpty()) - return notHandledByInterceptor(); - - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + // TODO(antonm): investigate what convertToNativeObject does for the case of DOMWINDOW. + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); if (!window) return notHandledByInterceptor(); @@ -800,12 +867,13 @@ NAMED_PROPERTY_GETTER(DOMWindow) return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); // Search IDL functions defined in the prototype - v8::Handle<v8::Value> result = holder->GetRealNamedPropertyInPrototypeChain(name); + v8::Handle<v8::Value> result = info.Holder()->GetRealNamedProperty(name); if (!result.IsEmpty()) return result; // Search named items in the document. Document* doc = frame->document(); + if (doc) { RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); if (items->length() >= 1) { @@ -826,13 +894,13 @@ void V8Custom::WindowSetLocation(DOMWindow* window, const String& relativeURL) if (!frame) return; - if (!shouldAllowNavigation(frame)) - return; - KURL url = completeURL(relativeURL); if (url.isNull()) return; + if (!shouldAllowNavigation(frame)) + return; + navigateIfAllowed(frame, url, false, false); } @@ -853,12 +921,15 @@ CALLBACK_FUNC_DECL(DOMWindowSetInterval) void V8Custom::ClearTimeoutImpl(const v8::Arguments& args) { + int handle = toInt32(args[0]); + v8::Handle<v8::Object> holder = args.Holder(); DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!V8Proxy::canAccessFrame(imp->frame(), true)) return; - ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->frame()->document()); - int handle = toInt32(args[0]); + ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->document()); + if (!context) + return; DOMTimer::removeById(context, handle); } diff --git a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp index 300e829..9ddd620 100644 --- a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp @@ -45,13 +45,50 @@ namespace WebCore { CALLBACK_FUNC_DECL(DatabaseChangeVersion) { INC_STATS("DOM.Database.changeVersion()"); + + if (args.Length() < 2) + return throwError("The old and new version strings are required.", V8Proxy::SyntaxError); + + if (!(args[0]->IsString() && args[1]->IsString())) + return throwError("The old and new versions must be strings."); + + Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, args.Holder()); + + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return v8::Undefined(); + + RefPtr<V8CustomSQLTransactionCallback> callback; + if (args.Length() > 2) { + if (!args[2]->IsObject()) + return throwError("changeVersion transaction callback must be of valid type."); + + callback = V8CustomSQLTransactionCallback::create(args[2], frame); + } + + RefPtr<V8CustomSQLTransactionErrorCallback> errorCallback; + if (args.Length() > 3) { + if (!args[3]->IsObject()) + return throwError("changeVersion error callback must be of valid type."); + + errorCallback = V8CustomSQLTransactionErrorCallback::create(args[3], frame); + } + + RefPtr<V8CustomVoidCallback> successCallback; + if (args.Length() > 4) { + if (!args[4]->IsObject()) + return throwError("changeVersion success callback must be of valid type."); + + successCallback = V8CustomVoidCallback::create(args[4], frame); + } + + database->changeVersion(toWebCoreString(args[0]), toWebCoreString(args[1]), callback.release(), errorCallback.release(), successCallback.release()); + return v8::Undefined(); } -CALLBACK_FUNC_DECL(DatabaseTransaction) +static v8::Handle<v8::Value> createTransaction(const v8::Arguments& args, bool readOnly) { - INC_STATS("DOM.Database.transaction()"); - if (!args.Length()) return throwError("Transaction callback is required.", V8Proxy::SyntaxError); @@ -76,18 +113,28 @@ CALLBACK_FUNC_DECL(DatabaseTransaction) RefPtr<V8CustomVoidCallback> successCallback; if (args.Length() > 2) { - if (!args[1]->IsObject()) + if (!args[2]->IsObject()) return throwError("Transaction success callback must be of valid type."); successCallback = V8CustomVoidCallback::create(args[2], frame); } - database->transaction(callback.release(), errorCallback.release(), successCallback.release()); - + database->transaction(callback.release(), errorCallback.release(), successCallback.release(), readOnly); return v8::Undefined(); } +CALLBACK_FUNC_DECL(DatabaseTransaction) +{ + INC_STATS("DOM.Database.transaction()"); + return createTransaction(args, false); +} + +CALLBACK_FUNC_DECL(DatabaseReadTransaction) +{ + INC_STATS("DOM.Database.readTransaction()"); + return createTransaction(args, true); +} + } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp index f13e45e..263c005 100644 --- a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp @@ -35,48 +35,26 @@ #include "WorkerContextExecutionProxy.h" #include "DedicatedWorkerContext.h" +#include "V8Binding.h" +#include "V8MessagePortCustom.h" #include "V8Proxy.h" #include "V8WorkerContextEventListener.h" namespace WebCore { -ACCESSOR_GETTER(DedicatedWorkerContextOnmessage) +CALLBACK_FUNC_DECL(DedicatedWorkerContextPostMessage) { - INC_STATS(L"DOM.DedicatedWorkerContext.onmessage._get"); - DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, info.Holder()); - if (workerContext->onmessage()) { - V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(DedicatedWorkerContextOnmessage) -{ - INC_STATS(L"DOM.DedicatedWorkerContext.onmessage._set"); - DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, info.Holder()); - V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); - if (value->IsNull()) { - if (workerContext->onmessage()) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kDedicatedWorkerContextRequestCacheIndex); - } - - // Clear the listener. - workerContext->setOnmessage(0); - } else { - RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), false, false); - if (listener) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kDedicatedWorkerContextRequestCacheIndex); - } - - workerContext->setOnmessage(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kDedicatedWorkerContextRequestCacheIndex); - } + INC_STATS(L"DOM.DedicatedWorkerContext.postMessage"); + DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, args.Holder()); + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(v8ValueToWebCoreString(args[0])); + MessagePortArray portArray; + if (args.Length() > 1) { + if (!getMessagePortArray(args[1], portArray)) + return v8::Undefined(); } + ExceptionCode ec = 0; + workerContext->postMessage(message.release(), &portArray, ec); + return throwError(ec); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp index 80d204b..ee68293 100644 --- a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp @@ -31,10 +31,12 @@ #include "config.h" #include "Document.h" +#include "CanvasRenderingContext.h" #include "ExceptionCode.h" #include "Node.h" #include "XPathNSResolver.h" #include "XPathResult.h" +#include "CanvasRenderingContext.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -62,12 +64,8 @@ CALLBACK_FUNC_DECL(DocumentEvaluate) if (V8Node::HasInstance(args[1])) contextNode = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])); - RefPtr<XPathNSResolver> resolver; - if (V8XPathNSResolver::HasInstance(args[2])) - resolver = V8DOMWrapper::convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(args[2])); - else if (args[2]->IsObject()) - resolver = V8CustomXPathNSResolver::create(args[2]->ToObject()); - else if (!args[2]->IsNull() && !args[2]->IsUndefined()) + RefPtr<XPathNSResolver> resolver = V8DOMWrapper::getXPathNSResolver(args[2], V8Proxy::retrieve(V8Proxy::retrieveFrameForCallingContext())); + if (!resolver && !args[2]->IsNull() && !args[2]->IsUndefined()) return throwError(TYPE_MISMATCH_ERR); int type = toInt32(args[3]); @@ -99,8 +97,17 @@ CALLBACK_FUNC_DECL(DocumentGetCSSCanvasContext) String name = toWebCoreString(args[1]); int width = toInt32(args[2]); int height = toInt32(args[3]); - CanvasRenderingContext2D* result = imp->getCSSCanvasContext(contextId, name, width, height); - return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); + CanvasRenderingContext* result = imp->getCSSCanvasContext(contextId, name, width, height); + if (!result) + return v8::Undefined(); + if (result->is2d()) + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); +#if ENABLE(3D_CANVAS) + else if (result->is3d()) + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLRENDERINGCONTEXT, result); +#endif // ENABLE(3D_CANVAS) + ASSERT_NOT_REACHED(); + return v8::Undefined(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8FileListCustom.cpp b/WebCore/bindings/v8/custom/V8FileListCustom.cpp new file mode 100644 index 0000000..bc533cf --- /dev/null +++ b/WebCore/bindings/v8/custom/V8FileListCustom.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FileList.h" + +#include "File.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +#include <wtf/RefPtr.h> + +namespace WebCore { + +INDEXED_PROPERTY_GETTER(FileList) +{ + INC_STATS("DOM.FileList.IndexedPropertyGetter"); + FileList* fileList = V8DOMWrapper::convertToNativeObject<FileList>(V8ClassIndex::FILELIST, info.Holder()); + RefPtr<File> file = fileList->item(index); + if (!file) + return notHandledByInterceptor(); + + return V8DOMWrapper::convertToV8Object(V8ClassIndex::FILE, file.release()); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp b/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp index 7bc687c..011beff 100644 --- a/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp @@ -1,49 +1,43 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright 2009, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" - #include "Geolocation.h" + #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8CustomPositionCallback.h" #include "V8CustomPositionErrorCallback.h" #include "V8Proxy.h" - using namespace std; using namespace WTF; namespace WebCore { -static const char* typeMismatchError = "TYPE_MISMATCH_ERR: DOM Exception 17"; +static const char typeMismatchError[] = "TYPE_MISMATCH_ERR: DOM Exception 17"; static void throwTypeMismatchException() { @@ -130,13 +124,7 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va return 0; } double timeoutDouble = timeoutNumber->Value(); - // V8 does not export a public symbol for infinity, so we must use a - // platform type. On Android, it seems that V8 uses 0xf70f000000000000, - // which is the standard way to represent infinity in a double. However, - // numeric_limits<double>::infinity uses the system HUGE_VAL, which is - // different. Therefore we test using isinf() and check that the value - // is positive, which seems to handle things correctly. - // If the value is infinity, there's nothing to do. + // If the value is positive infinity, there's nothing to do. if (!(isinf(timeoutDouble) && timeoutDouble > 0)) { v8::Local<v8::Int32> timeoutInt32 = timeoutValue->ToInt32(); if (timeoutInt32.IsEmpty()) { @@ -161,7 +149,7 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va } double maximumAgeDouble = maximumAgeNumber->Value(); if (isinf(maximumAgeDouble) && maximumAgeDouble > 0) { - // If the value is infinity, clear maximumAge. + // If the value is positive infinity, clear maximumAge. options->clearMaximumAge(); } else { v8::Local<v8::Int32> maximumAgeInt32 = maximumAgeValue->ToInt32(); diff --git a/WebCore/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp new file mode 100644 index 0000000..419f374 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HTMLAllCollection.h" + +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8NamedNodesCollection.h" +#include "V8Proxy.h" + +namespace WebCore { + +static v8::Handle<v8::Value> getNamedItems(HTMLAllCollection* collection, AtomicString name) +{ + Vector<RefPtr<Node> > namedItems; + collection->namedItems(name, namedItems); + + if (!namedItems.size()) + return v8::Handle<v8::Value>(); + + if (namedItems.size() == 1) + return V8DOMWrapper::convertNodeToV8Object(namedItems.at(0).release()); + + NodeList* list = new V8NamedNodesCollection(namedItems); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, list); +} + +static v8::Handle<v8::Value> getItem(HTMLAllCollection* collection, v8::Handle<v8::Value> argument) +{ + v8::Local<v8::Uint32> index = argument->ToArrayIndex(); + if (index.IsEmpty()) { + v8::Handle<v8::Value> result = getNamedItems(collection, toWebCoreString(argument->ToString())); + + if (result.IsEmpty()) + return v8::Undefined(); + + return result; + } + + RefPtr<Node> result = collection->item(index->Uint32Value()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); +} + +NAMED_PROPERTY_GETTER(HTMLAllCollection) +{ + INC_STATS("DOM.HTMLAllCollection.NamedPropertyGetter"); + // Search the prototype chain first. + v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); + + if (!value.IsEmpty()) + return value; + + // Search local callback properties next to find IDL defined + // properties. + if (info.Holder()->HasRealNamedCallbackProperty(name)) + return v8::Handle<v8::Value>(); + + // Finally, search the DOM structure. + HTMLAllCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLAllCollection>(V8ClassIndex::HTMLALLCOLLECTION, info.Holder()); + return getNamedItems(imp, v8StringToAtomicWebCoreString(name)); +} + +CALLBACK_FUNC_DECL(HTMLAllCollectionItem) +{ + INC_STATS("DOM.HTMLAllCollection.item()"); + HTMLAllCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLAllCollection>(V8ClassIndex::HTMLALLCOLLECTION, args.Holder()); + return getItem(imp, args[0]); +} + +CALLBACK_FUNC_DECL(HTMLAllCollectionNamedItem) +{ + INC_STATS("DOM.HTMLAllCollection.namedItem()"); + HTMLAllCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLAllCollection>(V8ClassIndex::HTMLALLCOLLECTION, args.Holder()); + v8::Handle<v8::Value> result = getNamedItems(imp, toWebCoreString(args[0])); + + if (result.IsEmpty()) + return v8::Undefined(); + + return result; +} + +CALLBACK_FUNC_DECL(HTMLAllCollectionCallAsFunction) +{ + INC_STATS("DOM.HTMLAllCollection.callAsFunction()"); + if (args.Length() < 1) + return v8::Undefined(); + + HTMLAllCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLAllCollection>(V8ClassIndex::HTMLALLCOLLECTION, args.Holder()); + + if (args.Length() == 1) + return getItem(imp, args[0]); + + // If there is a second argument it is the index of the item we want. + String name = toWebCoreString(args[0]); + v8::Local<v8::Uint32> index = args[1]->ToArrayIndex(); + if (index.IsEmpty()) + return v8::Undefined(); + + unsigned current = index->Uint32Value(); + Node* node = imp->namedItem(name); + while (node) { + if (!current) + return V8DOMWrapper::convertNodeToV8Object(node); + + node = imp->nextNamedItem(name); + current--; + } + + return v8::Undefined(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp index 6f9b761..c82d88a 100644 --- a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp @@ -29,8 +29,9 @@ */ #include "config.h" -#include "HTMLAudioElement.h" +#include "V8HTMLAudioElementConstructor.h" +#include "HTMLAudioElement.h" #include "Document.h" #include "Frame.h" #include "HTMLNames.h" @@ -42,6 +43,24 @@ namespace WebCore { +v8::Persistent<v8::FunctionTemplate> V8HTMLAudioElementConstructor::GetTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> cachedTemplate; + if (!cachedTemplate.IsEmpty()) + return cachedTemplate; + + v8::HandleScope scope; + v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLAudioElementConstructor)); + + v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate(); + instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount); + result->SetClassName(v8::String::New("HTMLAudioElement")); + result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLAUDIOELEMENT)); + + cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result); + return cachedTemplate; +} + CALLBACK_FUNC_DECL(HTMLAudioElementConstructor) { INC_STATS("DOM.HTMLAudioElement.Contructor"); @@ -62,8 +81,11 @@ CALLBACK_FUNC_DECL(HTMLAudioElementConstructor) V8DOMWrapper::convertNodeToV8Object(document); RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(HTMLNames::audioTag, document); - if (args.Length() > 0) + audio->setAutobuffer(true); + if (args.Length() > 0) { audio->setSrc(toWebCoreString(args[0])); + audio->scheduleLoad(); + } V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), audio.get()); audio->ref(); diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h new file mode 100755 index 0000000..ac4b46d --- /dev/null +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8HTMLAudioElementConstructor_h +#define V8HTMLAudioElementConstructor_h + +#include <v8.h> + +namespace WebCore { + +class V8HTMLAudioElementConstructor { +private: + static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + + friend class V8ClassIndex; +}; + +} + +#endif // V8HTMLAudioElementConstructor_h diff --git a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index 6ba9367..e51437e 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -30,7 +30,9 @@ #include "config.h" #include "HTMLCanvasElement.h" +#include "CanvasRenderingContext.h" +#include "CanvasRenderingContext.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Node.h" @@ -44,8 +46,17 @@ CALLBACK_FUNC_DECL(HTMLCanvasElementGetContext) v8::Handle<v8::Object> holder = args.Holder(); HTMLCanvasElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(holder); String contextId = toWebCoreString(args[0]); - CanvasRenderingContext2D* result = imp->getContext(contextId); - return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); + CanvasRenderingContext* result = imp->getContext(contextId); + if (!result) + return v8::Undefined(); + if (result->is2d()) + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); +#if ENABLE(3D_CANVAS) + else if (result->is3d()) + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLRENDERINGCONTEXT, result); +#endif + ASSERT_NOT_REACHED(); + return v8::Undefined(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp index a0c3d74..9cf2f3d 100644 --- a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp @@ -32,6 +32,7 @@ #include "HTMLDocument.h" #include "Frame.h" +#include "HTMLAllCollection.h" #include "HTMLCollection.h" #include "HTMLIFrameElement.h" #include "HTMLNames.h" @@ -119,8 +120,7 @@ CALLBACK_FUNC_DECL(HTMLDocumentWrite) INC_STATS("DOM.HTMLDocument.write()"); HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCallingContext(); - ASSERT(frame); - htmlDocument->write(writeHelperGetString(args), frame->document()); + htmlDocument->write(writeHelperGetString(args), frame ? frame->document() : NULL); return v8::Undefined(); } @@ -129,8 +129,7 @@ CALLBACK_FUNC_DECL(HTMLDocumentWriteln) INC_STATS("DOM.HTMLDocument.writeln()"); HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCallingContext(); - ASSERT(frame); - htmlDocument->writeln(writeHelperGetString(args), frame->document()); + htmlDocument->writeln(writeHelperGetString(args), frame ? frame->document() : NULL); return v8::Undefined(); } @@ -169,7 +168,7 @@ CALLBACK_FUNC_DECL(HTMLDocumentOpen) } Frame* frame = V8Proxy::retrieveFrameForCallingContext(); - htmlDocument->open(frame->document()); + htmlDocument->open(frame ? frame->document() : NULL); // Return the document. return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp index 4f865dd..2f55758 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp @@ -30,6 +30,7 @@ #include "config.h" #include "HTMLFrameElement.h" +#include "HTMLNames.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -37,6 +38,8 @@ namespace WebCore { +using namespace HTMLNames; + ACCESSOR_SETTER(HTMLFrameElementSrc) { HTMLFrameElement* frame = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameElement>(info.Holder()); @@ -45,7 +48,7 @@ ACCESSOR_SETTER(HTMLFrameElementSrc) if (!allowSettingFrameSrcToJavascriptUrl(frame, srcValue)) return; - frame->setSrc(srcValue); + frame->setAttribute(srcAttr, srcValue); } ACCESSOR_SETTER(HTMLFrameElementLocation) diff --git a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp index ce2c29a..a4863e8 100644 --- a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp @@ -30,6 +30,7 @@ #include "config.h" #include "HTMLIFrameElement.h" +#include "HTMLNames.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -37,6 +38,8 @@ namespace WebCore { +using namespace HTMLNames; + ACCESSOR_SETTER(HTMLIFrameElementSrc) { HTMLIFrameElement* iframe = V8DOMWrapper::convertDOMWrapperToNode<HTMLIFrameElement>(info.Holder()); @@ -45,7 +48,7 @@ ACCESSOR_SETTER(HTMLIFrameElementSrc) if (!allowSettingFrameSrcToJavascriptUrl(iframe, v)) return; - iframe->setSrc(v); + iframe->setAttribute(srcAttr, v); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp index 91ebd5f..71c99cf 100644 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp @@ -29,8 +29,9 @@ */ #include "config.h" -#include "HTMLImageElement.h" +#include "V8HTMLImageElementConstructor.h" +#include "HTMLImageElement.h" #include "Document.h" #include "Frame.h" #include "HTMLNames.h" @@ -42,6 +43,24 @@ namespace WebCore { +v8::Persistent<v8::FunctionTemplate> V8HTMLImageElementConstructor::GetTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> cachedTemplate; + if (!cachedTemplate.IsEmpty()) + return cachedTemplate; + + v8::HandleScope scope; + v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLImageElementConstructor)); + + v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate(); + instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount); + result->SetClassName(v8::String::New("HTMLImageElement")); + result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLIMAGEELEMENT)); + + cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result); + return cachedTemplate; +} + CALLBACK_FUNC_DECL(HTMLImageElementConstructor) { INC_STATS("DOM.HTMLImageElement.Contructor"); diff --git a/WebCore/bindings/v8/ScriptObjectQuarantine.h b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h index 3b7ccff..cdce0e0 100644..100755 --- a/WebCore/bindings/v8/ScriptObjectQuarantine.h +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h @@ -28,33 +28,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// ScriptObjectQuarantine is used in JSC for wrapping DOM objects of the page -// before they are passed to Inspector's front-end. The wrapping prevents -// malicious scripts from gaining privileges. For V8, we are currently just -// passing the object itself, without any wrapping. +#ifndef V8HTMLImageElementConstructor_h +#define V8HTMLImageElementConstructor_h -#ifndef ScriptObjectQuarantine_h -#define ScriptObjectQuarantine_h - -#include "ScriptState.h" +#include <v8.h> namespace WebCore { - class Database; - class DOMWindow; - class Frame; - class Node; - class ScriptObject; - class ScriptValue; - class Storage; - - ScriptValue quarantineValue(ScriptState*, const ScriptValue&); + class V8HTMLImageElementConstructor { + private: + static v8::Persistent<v8::FunctionTemplate> GetTemplate(); - bool getQuarantinedScriptObject(Database* database, ScriptObject& quarantinedObject); - bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& quarantinedObject); - bool getQuarantinedScriptObject(Node* node, ScriptObject& quarantinedObject); - bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedObject); + friend class V8ClassIndex; + }; } -#endif // ScriptObjectQuarantine_h +#endif // V8HTMLImageElementConstructor_h diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp index c22d127..f9c9cb4 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp @@ -29,8 +29,9 @@ */ #include "config.h" -#include "HTMLOptionElement.h" +#include "V8HTMLOptionElementConstructor.h" +#include "HTMLOptionElement.h" #include "Document.h" #include "Frame.h" #include "HTMLNames.h" @@ -43,6 +44,24 @@ namespace WebCore { +v8::Persistent<v8::FunctionTemplate> V8HTMLOptionElementConstructor::GetTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> cachedTemplate; + if (!cachedTemplate.IsEmpty()) + return cachedTemplate; + + v8::HandleScope scope; + v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLOptionElementConstructor)); + + v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate(); + instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount); + result->SetClassName(v8::String::New("HTMLOptionElement")); + result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLOPTIONELEMENT)); + + cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result); + return cachedTemplate; +} + CALLBACK_FUNC_DECL(HTMLOptionElementConstructor) { INC_STATS("DOM.HTMLOptionElement.Contructor"); diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h new file mode 100755 index 0000000..70076a5 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8HTMLOptionElementConstructor_h +#define V8HTMLOptionElementConstructor_h + +#include <v8.h> + +namespace WebCore { + + class V8HTMLOptionElementConstructor { + private: + static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + + friend class V8ClassIndex; + }; + +} + +#endif // V8HTMLOptionElementConstructor_h diff --git a/WebCore/bindings/v8/custom/V8HistoryCustom.cpp b/WebCore/bindings/v8/custom/V8HistoryCustom.cpp new file mode 100644 index 0000000..c884d15 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8HistoryCustom.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "History.h" + +#include "ExceptionCode.h" +#include "SerializedScriptValue.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { +CALLBACK_FUNC_DECL(HistoryPushState) +{ + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(toWebCoreString(args[0])); + + v8::TryCatch tryCatch; + String title = toWebCoreStringWithNullOrUndefinedCheck(args[1]); + if (tryCatch.HasCaught()) + return v8::Undefined(); + String url; + if (args.Length() > 2) { + url = toWebCoreStringWithNullOrUndefinedCheck(args[2]); + if (tryCatch.HasCaught()) + return v8::Undefined(); + } + + ExceptionCode ec = 0; + History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, args.Holder()); + history->stateObjectAdded(historyState.release(), title, url, History::StateObjectPush, ec); + return throwError(ec); +} + +CALLBACK_FUNC_DECL(HistoryReplaceState) +{ + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(toWebCoreString(args[0])); + + v8::TryCatch tryCatch; + String title = toWebCoreStringWithNullOrUndefinedCheck(args[1]); + if (tryCatch.HasCaught()) + return v8::Undefined(); + String url; + if (args.Length() > 2) { + url = toWebCoreStringWithNullOrUndefinedCheck(args[2]); + if (tryCatch.HasCaught()) + return v8::Undefined(); + } + + ExceptionCode ec = 0; + History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, args.Holder()); + history->stateObjectAdded(historyState.release(), title, url, History::StateObjectReplace, ec); + return throwError(ec); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp new file mode 100644 index 0000000..fac6733 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2007-2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InjectedScriptHost.h" + +#include "Database.h" +#include "DOMWindow.h" +#include "Frame.h" +#include "InspectorController.h" +#include "Node.h" +#include "Page.h" + +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(InjectedScriptHostInspectedWindow) +{ + INC_STATS("InjectedScriptHost.inspectedWindow()"); + + InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + InspectorController* ic = host->inspectorController(); + if (!ic) + return v8::Undefined(); + return V8DOMWrapper::convertToV8Object<DOMWindow>(V8ClassIndex::DOMWINDOW, ic->inspectedPage()->mainFrame()->domWindow()); +} + +CALLBACK_FUNC_DECL(InjectedScriptHostWrapCallback) +{ + INC_STATS("InjectedScriptHost.wrapCallback()"); + return args[0]; +} + +CALLBACK_FUNC_DECL(InjectedScriptHostNodeForId) +{ + INC_STATS("InjectedScriptHost.nodeForId()"); + if (args.Length() < 1) + return v8::Undefined(); + + InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + + Node* node = host->nodeForId(args[0]->ToInt32()->Value()); + if (!node) + return v8::Undefined(); + + InspectorController* ic = host->inspectorController(); + if (!ic) + return v8::Undefined(); + + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODE, node); +} + +CALLBACK_FUNC_DECL(InjectedScriptHostWrapObject) +{ + INC_STATS("InjectedScriptHost.wrapObject()"); + if (args.Length() < 2) + return v8::Undefined(); + + InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + return host->wrapObject(ScriptValue(args[0]), toWebCoreStringWithNullCheck(args[1])).v8Value(); +} + +CALLBACK_FUNC_DECL(InjectedScriptHostUnwrapObject) +{ + INC_STATS("InjectedScriptHost.unwrapObject()"); + if (args.Length() < 1) + return v8::Undefined(); + + InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + return host->unwrapObject(toWebCoreStringWithNullCheck(args[0])).v8Value(); +} + +CALLBACK_FUNC_DECL(InjectedScriptHostPushNodePathToFrontend) +{ + INC_STATS("InjectedScriptHost.pushNodePathToFrontend()"); + if (args.Length() < 2) + return v8::Undefined(); + + InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); + bool selectInUI = args[1]->ToBoolean()->Value(); + if (node) + return v8::Number::New(host->pushNodePathToFrontend(node, selectInUI)); + + return v8::Undefined(); +} + +#if ENABLE(DATABASE) +CALLBACK_FUNC_DECL(InjectedScriptHostDatabaseForId) +{ + INC_STATS("InjectedScriptHost.databaseForId()"); + if (args.Length() < 1) + return v8::Undefined(); + + InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + Database* database = host->databaseForId(args[0]->ToInt32()->Value()); + if (!database) + return v8::Undefined(); + return V8DOMWrapper::convertToV8Object<Database>(V8ClassIndex::DATABASE, database); +} + +CALLBACK_FUNC_DECL(InjectedScriptHostSelectDatabase) +{ + INC_STATS("InjectedScriptHost.selectDatabase()"); + if (args.Length() < 1) + return v8::Undefined(); + + InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, v8::Handle<v8::Object>::Cast(args[0])); + if (database) + host->selectDatabase(database); + + return v8::Undefined(); +} +#endif + +#if ENABLE(DOM_STORAGE) +CALLBACK_FUNC_DECL(InjectedScriptHostSelectDOMStorage) +{ + INC_STATS("InjectedScriptHost.selectDOMStorage()"); + if (args.Length() < 1) + return v8::Undefined(); + + InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, v8::Handle<v8::Object>::Cast(args[0])); + if (storage) + host->selectDOMStorage(storage); + + return v8::Undefined(); +} +#endif + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp deleted file mode 100644 index 2571df4..0000000 --- a/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2007-2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "InspectorBackend.h" - -#include "DOMWindow.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "ExceptionCode.h" -#include "InspectorController.h" -#include "InspectorResource.h" -#include "NotImplemented.h" -#include "Node.h" -#include "Range.h" -#include "Page.h" -#include "TextIterator.h" -#include "VisiblePosition.h" - -#include "V8Binding.h" -#include "V8CustomBinding.h" -#include "V8Proxy.h" - -namespace WebCore { - -CALLBACK_FUNC_DECL(InspectorBackendHighlightDOMNode) -{ - INC_STATS("InspectorBackend.highlightDOMNode()"); - - if (args.Length() < 1) - return v8::Undefined(); - - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); - if (!node) - return v8::Undefined(); - - InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); - inspectorBackend->highlight(node); - - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(InspectorBackendSearch) -{ - INC_STATS("InspectorBackend.search()"); - - if (args.Length() < 2) - return v8::Undefined(); - - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); - if (!node) - return v8::Undefined(); - - String target = toWebCoreStringWithNullCheck(args[1]); - if (target.isEmpty()) - return v8::Undefined(); - - v8::Local<v8::Array> result = v8::Array::New(); - RefPtr<Range> searchRange(rangeOfContents(node)); - - ExceptionCode ec = 0; - int index = 0; - do { - RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false)); - if (resultRange->collapsed(ec)) - break; - - // A non-collapsed result range can in some funky whitespace cases still not - // advance the range's start position (4509328). Break to avoid infinite loop. - VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); - if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) - break; - - result->Set(v8::Number::New(index++), V8DOMWrapper::convertToV8Object(V8ClassIndex::RANGE, resultRange.release())); - - setStart(searchRange.get(), newStart); - } while (true); - - return result; -} - -#if ENABLE(DATABASE) -CALLBACK_FUNC_DECL(InspectorBackendDatabaseTableNames) -{ - INC_STATS("InspectorBackend.databaseTableNames()"); - v8::Local<v8::Array> result = v8::Array::New(0); - return result; -} -#endif - -CALLBACK_FUNC_DECL(InspectorBackendInspectedWindow) -{ - INC_STATS("InspectorBackend.inspectedWindow()"); - - InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); - InspectorController* ic = inspectorBackend->inspectorController(); - if (!ic) - return v8::Undefined(); - return V8DOMWrapper::convertToV8Object<DOMWindow>(V8ClassIndex::DOMWINDOW, ic->inspectedPage()->mainFrame()->domWindow()); -} - -CALLBACK_FUNC_DECL(InspectorBackendSetting) -{ - INC_STATS("InspectorBackend.setting()"); - - if (args.Length() < 1) - return v8::Undefined(); - - String key = toWebCoreStringWithNullCheck(args[0]); - if (key.isEmpty()) - return v8::Undefined(); - - InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); - InspectorController* ic = inspectorBackend->inspectorController(); - if (!ic) - return v8::Undefined(); - const InspectorController::Setting& setting = ic->setting(key); - - switch (setting.type()) { - default: - case InspectorController::Setting::NoType: - return v8::Undefined(); - case InspectorController::Setting::StringType: - return v8String(setting.string()); - case InspectorController::Setting::DoubleType: - return v8::Number::New(setting.doubleValue()); - case InspectorController::Setting::IntegerType: - return v8::Number::New(setting.integerValue()); - case InspectorController::Setting::BooleanType: - return v8Boolean(setting.booleanValue()); - case InspectorController::Setting::StringVectorType: { - const Vector<String>& strings = setting.stringVector(); - v8::Local<v8::Array> stringsArray = v8::Array::New(strings.size()); - const unsigned length = strings.size(); - for (unsigned i = 0; i < length; ++i) - stringsArray->Set(v8::Number::New(i), v8String(strings[i])); - return stringsArray; - } - } -} - -CALLBACK_FUNC_DECL(InspectorBackendSetSetting) -{ - INC_STATS("InspectorBackend.setSetting()"); - if (args.Length() < 2) - return v8::Undefined(); - - String key = toWebCoreStringWithNullCheck(args[0]); - if (key.isEmpty()) - return v8::Undefined(); - - InspectorController::Setting setting; - - v8::Local<v8::Value> value = args[1]; - if (value->IsUndefined() || value->IsNull()) { - // Do nothing. The setting is already NoType. - ASSERT(setting.type() == InspectorController::Setting::NoType); - } else if (value->IsString()) - setting.set(toWebCoreStringWithNullCheck(value)); - else if (value->IsNumber()) - setting.set(value->NumberValue()); - else if (value->IsBoolean()) - setting.set(value->BooleanValue()); - else if (value->IsArray()) { - v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(value); - Vector<String> strings; - for (unsigned i = 0; i < v8Array->Length(); ++i) { - String item = toWebCoreString(v8Array->Get(v8::Integer::New(i))); - if (item.isEmpty()) - return v8::Undefined(); - strings.append(item); - } - setting.set(strings); - } else - return v8::Undefined(); - - InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); - InspectorController* ic = inspectorBackend->inspectorController(); - if (ic) - inspectorBackend->inspectorController()->setSetting(key, setting); - - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(InspectorBackendWrapCallback) -{ - INC_STATS("InspectorBackend.wrapCallback()"); - return args[0]; -} - -} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp new file mode 100644 index 0000000..15b45e9 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2007-2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InspectorFrontendHost.h" + +#include "ExceptionCode.h" +#include "InspectorController.h" +#include "Node.h" +#include "Range.h" +#include "Page.h" +#include "TextIterator.h" +#include "VisiblePosition.h" + +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(InspectorFrontendHostSearch) +{ + INC_STATS("InspectorFrontendHost.search()"); + + if (args.Length() < 2) + return v8::Undefined(); + + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); + if (!node) + return v8::Undefined(); + + String target = toWebCoreStringWithNullCheck(args[1]); + if (target.isEmpty()) + return v8::Undefined(); + + v8::Local<v8::Array> result = v8::Array::New(); + RefPtr<Range> searchRange(rangeOfContents(node)); + + ExceptionCode ec = 0; + int index = 0; + do { + RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false)); + if (resultRange->collapsed(ec)) + break; + + // A non-collapsed result range can in some funky whitespace cases still not + // advance the range's start position (4509328). Break to avoid infinite loop. + VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); + if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) + break; + + result->Set(v8::Number::New(index++), V8DOMWrapper::convertToV8Object(V8ClassIndex::RANGE, resultRange.release())); + + setStart(searchRange.get(), newStart); + } while (true); + + return result; +} + +CALLBACK_FUNC_DECL(InspectorFrontendHostShowContextMenu) +{ + return v8::Undefined(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8LocationCustom.cpp b/WebCore/bindings/v8/custom/V8LocationCustom.cpp index 3f3ff6b..1ed4c51 100644 --- a/WebCore/bindings/v8/custom/V8LocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8LocationCustom.cpp @@ -128,13 +128,13 @@ ACCESSOR_SETTER(LocationHref) if (!frame) return; - if (!shouldAllowNavigation(frame)) - return; - KURL url = completeURL(toWebCoreString(value)); if (url.isNull()) return; + if (!shouldAllowNavigation(frame)) + return; + navigateIfAllowed(frame, url, false, false); } @@ -274,7 +274,7 @@ CALLBACK_FUNC_DECL(LocationReload) return v8::Undefined(); if (!protocolIsJavaScript(frame->loader()->url())) - frame->loader()->scheduleRefresh(processingUserGesture()); + frame->redirectScheduler()->scheduleRefresh(processingUserGesture()); return v8::Undefined(); } @@ -288,13 +288,13 @@ CALLBACK_FUNC_DECL(LocationReplace) if (!frame) return v8::Undefined(); - if (!shouldAllowNavigation(frame)) - return v8::Undefined(); - KURL url = completeURL(toWebCoreString(args[0])); if (url.isNull()) return v8::Undefined(); + if (!shouldAllowNavigation(frame)) + return v8::Undefined(); + navigateIfAllowed(frame, url, true, true); return v8::Undefined(); } @@ -309,13 +309,13 @@ CALLBACK_FUNC_DECL(LocationAssign) if (!frame) return v8::Undefined(); - if (!shouldAllowNavigation(frame)) - return v8::Undefined(); - KURL url = completeURL(toWebCoreString(args[0])); if (url.isNull()) return v8::Undefined(); + if (!shouldAllowNavigation(frame)) + return v8::Undefined(); + navigateIfAllowed(frame, url, false, false); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp index f45aecf..ca02b16 100644 --- a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp @@ -36,6 +36,7 @@ #include "Document.h" #include "Frame.h" +#include "V8Utilities.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" @@ -52,16 +53,9 @@ CALLBACK_FUNC_DECL(MessageChannelConstructor) return throwError("DOM object constructor cannot be called as a function."); // Get the ScriptExecutionContext (WorkerContext or Document) - ScriptExecutionContext* context = 0; - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); - if (proxy) - context = proxy->workerContext(); - else { - Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); - if (!frame) - return v8::Undefined(); - context = frame->document(); - } + ScriptExecutionContext* context = getScriptExecutionContext(); + if (!context) + return v8::Undefined(); // Note: it's OK to let this RefPtr go out of scope because we also call // SetDOMWrapper(), which effectively holds a reference to obj. diff --git a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp new file mode 100644 index 0000000..c5af635 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MessageEvent.h" +#include "SerializedScriptValue.h" + +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8DOMWindow.h" +#include "V8MessagePortCustom.h" +#include "V8Proxy.h" + +namespace WebCore { + +ACCESSOR_GETTER(MessageEventPorts) +{ + INC_STATS("DOM.MessageEvent.ports"); + MessageEvent* event = V8DOMWrapper::convertToNativeObject<MessageEvent>(V8ClassIndex::MESSAGEEVENT, info.Holder()); + + MessagePortArray* ports = event->ports(); + if (!ports || ports->isEmpty()) + return v8::Null(); + + v8::Local<v8::Array> portArray = v8::Array::New(ports->size()); + for (size_t i = 0; i < ports->size(); ++i) + portArray->Set(v8::Integer::New(i), V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, (*ports)[i].get())); + + return portArray; +} + +CALLBACK_FUNC_DECL(MessageEventInitMessageEvent) +{ + INC_STATS("DOM.MessageEvent.initMessageEvent"); + MessageEvent* event = V8DOMWrapper::convertToNativeObject<MessageEvent>(V8ClassIndex::MESSAGEEVENT, args.Holder()); + String typeArg = v8ValueToWebCoreString(args[0]); + bool canBubbleArg = args[1]->BooleanValue(); + bool cancelableArg = args[2]->BooleanValue(); + RefPtr<SerializedScriptValue> dataArg = SerializedScriptValue::create(v8ValueToWebCoreString(args[3])); + String originArg = v8ValueToWebCoreString(args[4]); + String lastEventIdArg = v8ValueToWebCoreString(args[5]); + DOMWindow* sourceArg = V8DOMWindow::HasInstance(args[6]) ? V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, v8::Handle<v8::Object>::Cast(args[6])) : 0; + OwnPtr<MessagePortArray> portArray; + + if (!isUndefinedOrNull(args[7])) { + portArray = new MessagePortArray(); + if (!getMessagePortArray(args[7], *portArray)) + return v8::Undefined(); + } + event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg.release(), originArg, lastEventIdArg, sourceArg, portArray.release()); + return v8::Undefined(); + } + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp index 95d248c..0d8631f 100644 --- a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp @@ -32,66 +32,22 @@ #include "ExceptionCode.h" #include "MessagePort.h" +#include "SerializedScriptValue.h" #include "V8Binding.h" #include "V8CustomBinding.h" -#include "V8ObjectEventListener.h" +#include "V8MessagePortCustom.h" +#include "V8MessagePort.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContextExecutionProxy.h" namespace WebCore { -PassRefPtr<EventListener> getEventListener(MessagePort* messagePort, v8::Local<v8::Value> value, bool findOnly, bool createObjectEventListener) -{ - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (proxy) { - V8EventListenerList* list = proxy->objectListeners(); - return findOnly ? list->findWrapper(value, false) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); - } - -#if ENABLE(WORKERS) - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) - return workerContextProxy->findOrCreateEventListenerHelper(value, false, findOnly, createObjectEventListener); -#endif - - return PassRefPtr<EventListener>(); -} - -ACCESSOR_GETTER(MessagePortOnmessage) -{ - INC_STATS("DOM.MessagePort.onmessage._get"); - MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); - return V8DOMWrapper::convertEventListenerToV8Object(messagePort->onmessage()); -} - -ACCESSOR_SETTER(MessagePortOnmessage) -{ - INC_STATS("DOM.MessagePort.onmessage._set"); - MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); - if (value->IsNull()) { - if (messagePort->onmessage()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(messagePort->onmessage()); - removeHiddenDependency(info.Holder(), listener->getListenerObject(), V8Custom::kMessagePortRequestCacheIndex); - } - - // Clear the listener. - messagePort->setOnmessage(0); - - } else { - RefPtr<EventListener> listener = getEventListener(messagePort, value, false, false); - if (listener) { - messagePort->setOnmessage(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kMessagePortRequestCacheIndex); - } - } -} - CALLBACK_FUNC_DECL(MessagePortAddEventListener) { INC_STATS("DOM.MessagePort.addEventListener()"); MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - RefPtr<EventListener> listener = getEventListener(messagePort, args[1], false, true); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(messagePort, args[1], false, ListenerFindOrCreate); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -106,7 +62,7 @@ CALLBACK_FUNC_DECL(MessagePortRemoveEventListener) { INC_STATS("DOM.MessagePort.removeEventListener()"); MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - RefPtr<EventListener> listener = getEventListener(messagePort, args[1], true, true); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(messagePort, args[1], false, ListenerFindOnly); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -118,4 +74,64 @@ CALLBACK_FUNC_DECL(MessagePortRemoveEventListener) return v8::Undefined(); } +CALLBACK_FUNC_DECL(MessagePortPostMessage) +{ + INC_STATS("DOM.MessagePort.postMessage"); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0])); + MessagePortArray portArray; + if (args.Length() > 1) { + if (!getMessagePortArray(args[1], portArray)) + return v8::Undefined(); + } + ExceptionCode ec = 0; + messagePort->postMessage(message.release(), &portArray, ec); + return throwError(ec); +} + +bool getMessagePortArray(v8::Local<v8::Value> value, MessagePortArray& portArray) +{ + if (isUndefinedOrNull(value)) { + portArray.resize(0); + return true; + } + + if (!value->IsObject()) { + throwError("MessagePortArray argument must be an object"); + return false; + } + uint32_t length = 0; + v8::Local<v8::Object> ports = v8::Local<v8::Object>::Cast(value); + + if (value->IsArray()) { + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value); + length = array->Length(); + } else { + // Sequence-type object - get the length attribute + v8::Local<v8::Value> sequenceLength = ports->Get(v8::String::New("length")); + if (!sequenceLength->IsNumber()) { + throwError("MessagePortArray argument has no length attribute"); + return false; + } + length = sequenceLength->Uint32Value(); + } + portArray.resize(length); + + for (unsigned int i = 0; i < length; ++i) { + v8::Local<v8::Value> port = ports->Get(v8::Integer::New(i)); + // Validation of non-null objects, per HTML5 spec 8.3.3. + if (isUndefinedOrNull(port)) { + throwError(INVALID_STATE_ERR); + return false; + } + // Validation of Objects implementing an interface, per WebIDL spec 4.1.15. + if (!V8MessagePort::HasInstance(port)) { + throwError("MessagePortArray argument must contain only MessagePorts"); + return false; + } + portArray[i] = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, v8::Handle<v8::Object>::Cast(port)); + } + return true; +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8MessagePortCustom.h b/WebCore/bindings/v8/custom/V8MessagePortCustom.h new file mode 100644 index 0000000..7ab502b --- /dev/null +++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008, 2009 Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8MessagePortCustom_h +#define V8MessagePortCustom_h + +#include <v8.h> + +#include "MessagePort.h" + +namespace WebCore { + + // Helper function which pulls the values out of a JS sequence and into a MessagePortArray. + // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec and generates exceptions as appropriate. + // Returns true if the array was filled, or false if the passed value was not of an appropriate type. + bool getMessagePortArray(v8::Local<v8::Value>, MessagePortArray&); + +} // namespace WebCore + +#endif // V8MessagePortCustom_h diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp index 6b0d740..9b4b9aa 100644 --- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp @@ -39,76 +39,18 @@ #include "V8CustomBinding.h" #include "V8CustomEventListener.h" #include "V8Node.h" -#include "V8ObjectEventListener.h" #include "V8Proxy.h" #include <wtf/RefPtr.h> namespace WebCore { -static inline String toEventType(v8::Local<v8::String> value) -{ - String key = toWebCoreString(value); - ASSERT(key.startsWith("on")); - return key.substring(2); -} - -static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) -{ - V8Proxy* proxy = V8Proxy::retrieve(node->scriptExecutionContext()); - // The document might be created using createDocument, which does - // not have a frame, use the active frame. - if (!proxy) - proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext()); - - if (proxy) { - V8EventListenerList* list = proxy->objectListeners(); - return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); - } - - return 0; -} - -ACCESSOR_SETTER(NodeEventHandler) -{ - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder()); - String eventType = toEventType(name); - - // Remove hidden dependency on the old event handler. - if (EventListener* listener = node->getAttributeEventListener(eventType)) { - if (static_cast<V8AbstractEventListener*>(listener)->isObjectListener()) { - v8::Local<v8::Object> v8Listener = static_cast<V8ObjectEventListener*>(listener)->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kNodeEventListenerCacheIndex); - } - } - - // Set handler if the value is a function. - if (value->IsFunction()) { - RefPtr<EventListener> listener = getEventListener(node, value, true, false); - if (listener) { - node->setAttributeEventListener(eventType, listener); - createHiddenDependency(info.Holder(), value, V8Custom::kNodeEventListenerCacheIndex); - } - } else { - // Otherwise, clear the handler. - node->clearAttributeEventListener(eventType); - } -} - -ACCESSOR_GETTER(NodeEventHandler) -{ - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder()); - - EventListener* listener = node->getAttributeEventListener(toEventType(name)); - return V8DOMWrapper::convertEventListenerToV8Object(listener); -} - CALLBACK_FUNC_DECL(NodeAddEventListener) { INC_STATS("DOM.Node.addEventListener()"); Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); - RefPtr<EventListener> listener = getEventListener(node, args[1], false, false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(node, args[1], false, ListenerFindOrCreate); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -126,9 +68,9 @@ CALLBACK_FUNC_DECL(NodeRemoveEventListener) // It is possbile that the owner document of the node is detached // from the frame. // See issue http://b/878909 - RefPtr<EventListener> listener = getEventListener(node, args[1], false, true); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(node, args[1], false, ListenerFindOnly); if (listener) { - String type = toWebCoreString(args[0]); + AtomicString type = v8ValueToAtomicWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); node->removeEventListener(type, listener.get(), useCapture); removeHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); diff --git a/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp new file mode 100644 index 0000000..a1f20cc --- /dev/null +++ b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(NOTIFICATIONS) + +#include "NotImplemented.h" +#include "Notification.h" +#include "NotificationCenter.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8CustomEventListener.h" +#include "V8CustomVoidCallback.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(NotificationAddEventListener) +{ + INC_STATS("DOM.Notification.addEventListener()"); + Notification* notification = V8DOMWrapper::convertToNativeObject<Notification>(V8ClassIndex::NOTIFICATION, args.Holder()); + + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(notification, args[1], false, ListenerFindOrCreate); + if (listener) { + String type = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + notification->addEventListener(type, listener, useCapture); + createHiddenDependency(args.Holder(), args[1], V8Custom::kNotificationRequestCacheIndex); + } + + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(NotificationRemoveEventListener) +{ + INC_STATS("DOM.Notification.removeEventListener()"); + Notification* notification = V8DOMWrapper::convertToNativeObject<Notification>(V8ClassIndex::NOTIFICATION, args.Holder()); + + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(notification, args[1], false, ListenerFindOnly); + if (listener) { + String type = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + notification->removeEventListener(type, listener.get(), useCapture); + removeHiddenDependency(args.Holder(), args[1], V8Custom::kNotificationRequestCacheIndex); + } + + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(NotificationCenterCreateHTMLNotification) +{ + INC_STATS(L"DOM.NotificationCenter.CreateHTMLNotification()"); + NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder()); + + ExceptionCode ec = 0; + String url = toWebCoreString(args[0]); + RefPtr<Notification> notification = notificationCenter->createHTMLNotification(url, ec); + + if (ec) + return throwError(ec); + + if (notificationCenter->context()->isWorkerContext()) + return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get()); + + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get()); +} + +CALLBACK_FUNC_DECL(NotificationCenterCreateNotification) +{ + INC_STATS(L"DOM.NotificationCenter.CreateNotification()"); + NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder()); + + ExceptionCode ec = 0; + RefPtr<Notification> notification = notificationCenter->createNotification(toWebCoreString(args[0]), toWebCoreString(args[1]), toWebCoreString(args[2]), ec); + + if (ec) + return throwError(ec); + + if (notificationCenter->context()->isWorkerContext()) + return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get()); + + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get()); +} + +CALLBACK_FUNC_DECL(NotificationCenterRequestPermission) +{ + INC_STATS(L"DOM.NotificationCenter.RequestPermission()"); + NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder()); + ScriptExecutionContext* context = notificationCenter->context(); + + // Requesting permission is only valid from a page context. + if (context->isWorkerContext()) + return throwError(NOT_SUPPORTED_ERR); + + RefPtr<V8CustomVoidCallback> callback; + if (args.Length() > 0) { + if (!args[0]->IsObject()) + return throwError("Callback must be of valid type.", V8Proxy::TypeError); + + callback = V8CustomVoidCallback::create(args[0], V8Proxy::retrieveFrameForCurrentContext()); + } + + notificationCenter->requestPermission(callback.release()); + return v8::Undefined(); +} + + +} // namespace WebCore + +#endif // ENABLE(NOTIFICATIONS) diff --git a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp index ce9c345..dff4ff4 100644 --- a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp @@ -49,15 +49,12 @@ CALLBACK_FUNC_DECL(SVGElementInstanceAddEventListener) INC_STATS("DOM.SVGElementInstance.AddEventListener()"); SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder()); - V8Proxy* proxy = V8Proxy::retrieve(instance->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(instance, args[1], false, ListenerFindOrCreate); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); instance->addEventListener(type, listener, useCapture); + createHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); } return v8::Undefined(); @@ -68,15 +65,12 @@ CALLBACK_FUNC_DECL(SVGElementInstanceRemoveEventListener) INC_STATS("DOM.SVGElementInstance.RemoveEventListener()"); SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder()); - V8Proxy* proxy = V8Proxy::retrieve(instance->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(instance, args[1], false, ListenerFindOnly); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); instance->removeEventListener(type, listener.get(), useCapture); + removeHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); } return v8::Undefined(); diff --git a/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp b/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp index 3766397..690eac1 100644 --- a/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp @@ -38,11 +38,27 @@ #include "V8Binding.h" #include "V8CustomBinding.h" +#include "V8SVGMatrix.h" #include "V8SVGPODTypeWrapper.h" #include "V8Proxy.h" namespace WebCore { +CALLBACK_FUNC_DECL(SVGMatrixMultiply) +{ + INC_STATS("DOM.SVGMatrix.multiply()"); + if (args.Length() < 1) + return throwError("Not enough arguments"); + + if (!V8SVGMatrix::HasInstance(args[0])) + return throwError("secondMatrix argument was not a SVGMatrix"); + + TransformationMatrix m1 = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); + TransformationMatrix m2 = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, v8::Handle<v8::Object>::Cast(args[0])); + + return V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGMATRIX, V8SVGStaticPODTypeWrapper<TransformationMatrix>::create(m1.multLeft(m2))); +} + CALLBACK_FUNC_DECL(SVGMatrixInverse) { INC_STATS("DOM.SVGMatrix.inverse()"); diff --git a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp index 3ab2f8e..de53ac7 100644 --- a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp @@ -38,7 +38,6 @@ #include "Frame.h" #include "V8Binding.h" #include "V8CustomBinding.h" -#include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContext.h" @@ -53,12 +52,15 @@ CALLBACK_FUNC_DECL(SharedWorkerConstructor) if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - if (args.Length() < 2) + if (!args.Length()) return throwError("Not enough arguments", V8Proxy::SyntaxError); v8::TryCatch tryCatch; v8::Handle<v8::String> scriptUrl = args[0]->ToString(); - v8::Handle<v8::String> name = args[1]->ToString(); + String name; + if (args.Length() > 1) + name = toWebCoreString(args[1]->ToString()); + if (tryCatch.HasCaught()) return throwError(tryCatch.Exception()); @@ -66,28 +68,23 @@ CALLBACK_FUNC_DECL(SharedWorkerConstructor) return v8::Undefined(); // Get the script execution context. - ScriptExecutionContext* context = 0; - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); - if (proxy) - context = proxy->workerContext(); - else { - Frame* frame = V8Proxy::retrieveFrame(); - if (!frame) - return v8::Undefined(); - context = frame->document(); - } - - // Create the worker object. + ScriptExecutionContext* context = getScriptExecutionContext(); + if (!context) + return v8::Undefined(); + + // Create the SharedWorker object. // Note: it's OK to let this RefPtr go out of scope because we also call SetDOMWrapper(), which effectively holds a reference to obj. ExceptionCode ec = 0; - RefPtr<SharedWorker> obj = SharedWorker::create(toWebCoreString(scriptUrl), toWebCoreString(name), context, ec); + RefPtr<SharedWorker> obj = SharedWorker::create(toWebCoreString(scriptUrl), name, context, ec); + if (ec) + return throwError(ec); // Setup the standard wrapper object internal fields. v8::Handle<v8::Object> wrapperObject = args.Holder(); - V8Proxy::setDOMWrapper(wrapperObject, V8ClassIndex::SHAREDWORKER, obj.get()); + V8DOMWrapper::setDOMWrapper(wrapperObject, V8ClassIndex::SHAREDWORKER, obj.get()); obj->ref(); - V8Proxy::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); + V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); return wrapperObject; } diff --git a/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp b/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp index ecd0153..32a48eb 100644 --- a/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp @@ -29,6 +29,7 @@ */ #include "config.h" +#include "HTMLStyleElement.h" #include "StyleSheetList.h" #include "V8Binding.h" @@ -50,7 +51,7 @@ NAMED_PROPERTY_GETTER(StyleSheetList) if (!item) return notHandledByInterceptor(); - return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLSTYLEELEMENT, item); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::STYLESHEET, item->sheet()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp new file mode 100644 index 0000000..16a1f51 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebGLArrayBufferConstructor) +{ + INC_STATS("DOM.WebGLArrayBuffer.Constructor"); + + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function."); + + // If we return a previously constructed WebGLArrayBuffer, + // e.g. from the call to WebGLArray.buffer, this code is called + // with a zero-length argument list. The V8DOMWrapper will then + // set the internal pointer in the newly-created object. + // Unfortunately it doesn't look like it's possible to distinguish + // between this case and that where the user calls "new + // WebGLArrayBuffer()" from JavaScript. To guard against problems, + // we always create at least a zero-length WebGLArrayBuffer, even + // if it is immediately overwritten by the V8DOMWrapper. + + // Supported constructors: + // WebGLArrayBuffer(n) where n is an integer: + // -- create an empty buffer of n bytes + + int argLen = args.Length(); + if (argLen > 1) + return throwError("Wrong number of arguments specified to constructor (requires 1)"); + + int len = 0; + if (argLen > 0) { + if (!args[0]->IsInt32()) + return throwError("Argument to WebGLArrayBuffer constructor was not an integer"); + len = toInt32(args[0]); + } + + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(len); + // Transform the holder into a wrapper object for the array. + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBGLARRAYBUFFER), buffer.get()); + return toV8(buffer.release(), args.Holder()); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h new file mode 100644 index 0000000..1a4b6a4 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +// Template function used by the WebGLArray*Constructor callbacks. +template<class ArrayClass> +v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, + int classIndex) +{ + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function."); + + int argLen = args.Length(); + if (argLen == 0) { + // This happens when we return a previously constructed + // WebGLArray, e.g. from the call to WebGL<T>Array.slice(). + // The V8DOMWrapper will set the internal pointer in the + // created object. Unfortunately it doesn't look like it's + // possible to distinguish between this case and that where + // the user calls "new WebGL<T>Array()" from JavaScript. + return args.Holder(); + } + + // Supported constructors: + // WebGL<T>Array(n) where n is an integer: + // -- create an empty array of n elements + // WebGL<T>Array(arr) where arr is an array: + // -- create a WebGL<T>Array containing the contents of "arr" + // WebGL<T>Array(buf, offset, length) + // -- create a WebGL<T>Array pointing to the WebGLArrayBuffer + // "buf", starting at the specified offset, for the given + // length + + // See whether the first argument is a WebGLArrayBuffer. + if (V8WebGLArrayBuffer::HasInstance(args[0])) { + if (argLen > 3) + return throwError("Wrong number of arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); + + WebGLArrayBuffer* buf = + V8DOMWrapper::convertToNativeObject<WebGLArrayBuffer>(V8ClassIndex::WEBGLARRAYBUFFER, + args[0]->ToObject()); + if (buf == NULL) + return throwError("Could not convert argument 0 to a WebGLArrayBuffer"); + bool ok; + int offset = 0; + if (argLen > 1) { + offset = toInt32(args[1], ok); + if (!ok) + return throwError("Could not convert argument 1 to an integer"); + } + int length = buf->byteLength() - offset; + if (argLen > 2) { + length = toInt32(args[2], ok); + if (!ok) + return throwError("Could not convert argument 2 to an integer"); + } + if (length < 0) + return throwError("Length / offset out of range"); + + RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length); + if (array == NULL) + return throwError("Invalid arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); + // Transform the holder into a wrapper object for the array. + V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get()); + V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(), + classIndex, + array.get()->baseAddress(), + array.get()->length()); + return toV8(array.release(), args.Holder()); + } + + int len = 0; + v8::Handle<v8::Object> srcArray; + if (argLen != 1) + return throwError("Wrong number of arguments to new WebGL<T>Array(int / array)"); + + if (args[0]->IsInt32()) { + len = toInt32(args[0]); + } else if (args[0]->IsObject()) { + srcArray = args[0]->ToObject(); + if (srcArray.IsEmpty()) + return throwError("Could not convert argument 0 to an object"); + len = toInt32(srcArray->Get(v8::String::New("length"))); + } else + return throwError("Could not convert argument 0 to either an int32 or an object"); + + RefPtr<ArrayClass> array = ArrayClass::create(len); + if (!srcArray.IsEmpty()) { + // Need to copy the incoming array into the newly created WebGLArray. + for (int i = 0; i < len; i++) { + v8::Local<v8::Value> val = srcArray->Get(v8::Integer::New(i)); + array->set(i, val->NumberValue()); + } + } + + // Transform the holder into a wrapper object for the array. + V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get()); + V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(), + classIndex, + array.get()->baseAddress(), + array.get()->length()); + return toV8(array.release(), args.Holder()); +} + +template <class T, typename ElementType> +v8::Handle<v8::Value> getWebGLArrayElement(const v8::Arguments& args, + V8ClassIndex::V8WrapperType wrapperType) +{ + if (args.Length() != 1) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + bool ok; + uint32_t index = toInt32(args[0], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + T* array = V8DOMWrapper::convertToNativeObject<T>(wrapperType, args.Holder()); + if (index >= array->length()) + return v8::Undefined(); + ElementType result; + if (!array->get(index, result)) + return v8::Undefined(); + return v8::Number::New(result); +} + +template <class T> +v8::Handle<v8::Value> setWebGLArrayFromArray(T* webGLArray, const v8::Arguments& args) +{ + if (args[0]->IsObject()) { + // void set(in sequence<long> array, [Optional] in unsigned long offset); + v8::Local<v8::Object> array = args[0]->ToObject(); + uint32_t offset = 0; + if (args.Length() == 2) + offset = toInt32(args[1]); + uint32_t length = toInt32(array->Get(v8::String::New("length"))); + for (uint32_t i = 0; i < length; i++) { + webGLArray->set(offset + i, array->Get(v8::Integer::New(i))->NumberValue()); + } + } + + return v8::Undefined(); +} + +template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType> +v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, + V8ClassIndex::V8WrapperType wrapperType) +{ + if (args.Length() < 1 || args.Length() > 2) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + CPlusPlusArrayType* array = V8DOMWrapper::convertToNativeObject<CPlusPlusArrayType>(wrapperType, args.Holder()); + + if (args.Length() == 2 && args[0]->IsInt32()) { + // void set(in unsigned long index, in long value); + uint32_t index = toInt32(args[0]); + array->set(index, args[1]->NumberValue()); + return v8::Undefined(); + } + + if (JavaScriptWrapperArrayType::HasInstance(args[0])) { + // void set(in WebGL<T>Array array, [Optional] in unsigned long offset); + CPlusPlusArrayType* src = V8DOMWrapper::convertToNativeObject<CPlusPlusArrayType>(wrapperType, args[0]->ToObject()); + uint32_t offset = 0; + if (args.Length() == 2) + offset = toInt32(args[1]); + ExceptionCode ec = 0; + array->set(src, offset, ec); + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + + return setWebGLArrayFromArray(array, args); +} + +} + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp new file mode 100644 index 0000000..5719c8a --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" +#include "WebGLByteArray.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8WebGLArrayCustom.h" +#include "V8WebGLByteArray.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebGLByteArrayConstructor) +{ + INC_STATS("DOM.WebGLByteArray.Contructor"); + + return constructWebGLArray<WebGLByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLBYTEARRAY)); +} + +// Get the specified value from the byte buffer and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid byte buffer range return "undefined". +INDEXED_PROPERTY_GETTER(WebGLByteArray) +{ + INC_STATS("DOM.WebGLByteArray.IndexedPropertyGetter"); + WebGLByteArray* byteBuffer = V8DOMWrapper::convertToNativeObject<WebGLByteArray>(V8ClassIndex::WEBGLBYTEARRAY, info.Holder()); + + if ((index < 0) || (index >= byteBuffer->length())) + return v8::Undefined(); + signed char result; + if (!byteBuffer->get(index, result)) + return v8::Undefined(); + return v8::Number::New(result); +} + +// Set the specified value in the byte buffer. Accesses outside the valid byte buffer range are silently ignored. +INDEXED_PROPERTY_SETTER(WebGLByteArray) +{ + INC_STATS("DOM.WebGLByteArray.IndexedPropertySetter"); + WebGLByteArray* array = V8DOMWrapper::convertToNativeObject<WebGLByteArray>(V8ClassIndex::WEBGLBYTEARRAY, info.Holder()); + + if ((index >= 0) && (index < array->length())) { + if (!value->IsNumber()) + return throwError("Could not convert value argument to a number"); + array->set(index, value->NumberValue()); + } + return value; +} + +CALLBACK_FUNC_DECL(WebGLByteArrayGet) +{ + INC_STATS("DOM.WebGLByteArray.get()"); + return getWebGLArrayElement<WebGLByteArray, signed char>(args, V8ClassIndex::WEBGLBYTEARRAY); +} + +CALLBACK_FUNC_DECL(WebGLByteArraySet) +{ + INC_STATS("DOM.WebGLByteArray.set()"); + return setWebGLArray<WebGLByteArray, V8WebGLByteArray>(args, V8ClassIndex::WEBGLBYTEARRAY); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp new file mode 100644 index 0000000..6e56760 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" +#include "WebGLFloatArray.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8WebGLArrayCustom.h" +#include "V8WebGLFloatArray.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebGLFloatArrayConstructor) +{ + INC_STATS("DOM.WebGLFloatArray.Contructor"); + + return constructWebGLArray<WebGLFloatArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLFLOATARRAY)); +} + +// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined". +INDEXED_PROPERTY_GETTER(WebGLFloatArray) +{ + INC_STATS("DOM.WebGLFloatArray.IndexedPropertyGetter"); + WebGLFloatArray* array = V8DOMWrapper::convertToNativeObject<WebGLFloatArray>(V8ClassIndex::WEBGLFLOATARRAY, info.Holder()); + + if ((index < 0) || (index >= array->length())) + return v8::Undefined(); + float result; + if (!array->get(index, result)) + return v8::Undefined(); + return v8::Number::New(result); +} + +// Set the specified value in the array. Accesses outside the valid array range are silently ignored. +INDEXED_PROPERTY_SETTER(WebGLFloatArray) +{ + INC_STATS("DOM.WebGLFloatArray.IndexedPropertySetter"); + WebGLFloatArray* array = V8DOMWrapper::convertToNativeObject<WebGLFloatArray>(V8ClassIndex::WEBGLFLOATARRAY, info.Holder()); + + if ((index >= 0) && (index < array->length())) + array->set(index, value->NumberValue()); + return value; +} + +CALLBACK_FUNC_DECL(WebGLFloatArrayGet) +{ + INC_STATS("DOM.WebGLFloatArray.get()"); + return getWebGLArrayElement<WebGLFloatArray, float>(args, V8ClassIndex::WEBGLFLOATARRAY); +} + +CALLBACK_FUNC_DECL(WebGLFloatArraySet) +{ + INC_STATS("DOM.WebGLFloatArray.set()"); + return setWebGLArray<WebGLFloatArray, V8WebGLFloatArray>(args, V8ClassIndex::WEBGLFLOATARRAY); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp new file mode 100644 index 0000000..1bd30b2 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" +#include "WebGLIntArray.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8WebGLArrayCustom.h" +#include "V8WebGLIntArray.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebGLIntArrayConstructor) +{ + INC_STATS("DOM.WebGLIntArray.Contructor"); + + return constructWebGLArray<WebGLIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLINTARRAY)); +} + +// Get the specified value from the integer array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid pixel buffer range return "undefined". +INDEXED_PROPERTY_GETTER(WebGLIntArray) +{ + INC_STATS("DOM.WebGLIntArray.IndexedPropertyGetter"); + WebGLIntArray* array = V8DOMWrapper::convertToNativeObject<WebGLIntArray>(V8ClassIndex::WEBGLINTARRAY, info.Holder()); + + if ((index < 0) || (index >= array->length())) + return v8::Undefined(); + int result; + if (!array->get(index, result)) + return v8::Undefined(); + return v8::Number::New(result); +} + +// Set the specified value in the integer array. Accesses outside the valid integer array range are silently ignored. +INDEXED_PROPERTY_SETTER(WebGLIntArray) +{ + INC_STATS("DOM.WebGLIntArray.IndexedPropertySetter"); + WebGLIntArray* array = V8DOMWrapper::convertToNativeObject<WebGLIntArray>(V8ClassIndex::WEBGLINTARRAY, info.Holder()); + + if ((index >= 0) && (index < array->length())) { + if (!value->IsNumber()) + return throwError("Could not convert value argument to a number"); + array->set(index, value->NumberValue()); + } + return value; +} + +CALLBACK_FUNC_DECL(WebGLIntArrayGet) +{ + INC_STATS("DOM.WebGLIntArray.get()"); + return getWebGLArrayElement<WebGLIntArray, int>(args, V8ClassIndex::WEBGLINTARRAY); +} + +CALLBACK_FUNC_DECL(WebGLIntArraySet) +{ + INC_STATS("DOM.WebGLIntArray.set()"); + return setWebGLArray<WebGLIntArray, V8WebGLIntArray>(args, V8ClassIndex::WEBGLINTARRAY); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp new file mode 100644 index 0000000..fd73a5b --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp @@ -0,0 +1,928 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions areV8ClassIndex::WEBGL + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLRenderingContext.h" + +#include "ExceptionCode.h" + +#include "NotImplemented.h" + +#include <wtf/FastMalloc.h> + +#include "V8Binding.h" +#include "V8WebGLArray.h" +#include "V8WebGLByteArray.h" +#include "V8WebGLFloatArray.h" +#include "V8WebGLIntArray.h" +#include "V8WebGLProgram.h" +#include "V8WebGLShader.h" +#include "V8WebGLShortArray.h" +#include "V8WebGLUniformLocation.h" +#include "V8WebGLUnsignedByteArray.h" +#include "V8WebGLUnsignedIntArray.h" +#include "V8WebGLUnsignedShortArray.h" +#include "V8HTMLCanvasElement.h" +#include "V8HTMLImageElement.h" +#include "V8Proxy.h" + +namespace WebCore { + +// Allocates new storage via tryFastMalloc. +// Returns NULL if array failed to convert for any reason. +static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len) +{ + // Convert the data element-by-element. + float* data; + if (!tryFastMalloc(len * sizeof(float)).getValue(data)) + return 0; + for (uint32_t i = 0; i < len; i++) { + v8::Local<v8::Value> val = array->Get(v8::Integer::New(i)); + if (!val->IsNumber()) { + fastFree(data); + return 0; + } + data[i] = toFloat(val); + } + return data; +} + +// Allocates new storage via tryFastMalloc. +// Returns NULL if array failed to convert for any reason. +static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len) +{ + // Convert the data element-by-element. + int* data; + if (!tryFastMalloc(len * sizeof(int)).getValue(data)) + return 0; + for (uint32_t i = 0; i < len; i++) { + v8::Local<v8::Value> val = array->Get(v8::Integer::New(i)); + bool ok; + int ival = toInt32(val, ok); + if (!ok) { + fastFree(data); + return 0; + } + data[i] = ival; + } + return data; +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextBufferData) +{ + INC_STATS("DOM.WebGLRenderingContext.bufferData()"); + + // Forms: + // * bufferData(GLenum target, WebGLArray data, GLenum usage); + // - Sets the buffer's data from the given WebGLArray + // * bufferData(GLenum target, GLsizeiptr size, GLenum usage); + // - Sets the size of the buffer to the given size in bytes + if (args.Length() != 3) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + bool ok; + int target = toInt32(args[0], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int usage = toInt32(args[2], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + if (args[1]->IsInt32()) { + int size = toInt32(args[1]); + ExceptionCode exceptionCode; + context->bufferData(target, size, usage, exceptionCode); + } else if (V8WebGLArray::HasInstance(args[1])) { + WebGLArray* array = V8DOMWrapper::convertToNativeObject<WebGLArray>(V8ClassIndex::WEBGLARRAY, args[1]->ToObject()); + ExceptionCode exceptionCode; + context->bufferData(target, array, usage, exceptionCode); + } else { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextBufferSubData) +{ + INC_STATS("DOM.WebGLRenderingContext.bufferSubData()"); + + // Forms: + // * bufferSubData(GLenum target, GLintptr offset, WebGLArray data); + if (args.Length() != 3) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + bool ok; + int target = toInt32(args[0], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int offset = toInt32(args[1], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + if (!V8WebGLArray::HasInstance(args[2])) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + WebGLArray* array = V8DOMWrapper::convertToNativeObject<WebGLArray>(V8ClassIndex::WEBGLARRAY, args[2]->ToObject()); + ExceptionCode exceptionCode; + context->bufferSubData(target, offset, array, exceptionCode); + return v8::Undefined(); +} + +static v8::Handle<v8::Value> toV8(const WebGLGetInfo& info) +{ + switch (info.getType()) { + case WebGLGetInfo::kTypeBool: + return v8::Boolean::New(info.getBool()); + case WebGLGetInfo::kTypeFloat: + return v8::Number::New(info.getFloat()); + case WebGLGetInfo::kTypeLong: + return v8::Integer::New(info.getLong()); + case WebGLGetInfo::kTypeNull: + return v8::Null(); + case WebGLGetInfo::kTypeString: + return v8::String::New(fromWebCoreString(info.getString()), info.getString().length()); + case WebGLGetInfo::kTypeUnsignedLong: + return v8::Integer::NewFromUnsigned(info.getUnsignedLong()); + case WebGLGetInfo::kTypeWebGLBuffer: + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLBUFFER, info.getWebGLBuffer()); + case WebGLGetInfo::kTypeWebGLFloatArray: + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLFLOATARRAY, info.getWebGLFloatArray()); + case WebGLGetInfo::kTypeWebGLFramebuffer: + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLFRAMEBUFFER, info.getWebGLFramebuffer()); + case WebGLGetInfo::kTypeWebGLIntArray: + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLINTARRAY, info.getWebGLIntArray()); + // FIXME: implement WebGLObjectArray + // case WebGLGetInfo::kTypeWebGLObjectArray: + case WebGLGetInfo::kTypeWebGLProgram: + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLPROGRAM, info.getWebGLProgram()); + case WebGLGetInfo::kTypeWebGLRenderbuffer: + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLRENDERBUFFER, info.getWebGLRenderbuffer()); + case WebGLGetInfo::kTypeWebGLTexture: + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLTEXTURE, info.getWebGLTexture()); + case WebGLGetInfo::kTypeWebGLUnsignedByteArray: + return V8DOMWrapper::convertToV8Object(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY, info.getWebGLUnsignedByteArray()); + default: + notImplemented(); + return v8::Undefined(); + } +} + +enum ObjectType { + kBuffer, kRenderbuffer, kTexture, kVertexAttrib +}; + +static v8::Handle<v8::Value> getObjectParameter(const v8::Arguments& args, ObjectType objectType) +{ + if (args.Length() != 2) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + ExceptionCode ec = 0; + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + bool ok; + unsigned target = toInt32(args[0], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + unsigned pname = toInt32(args[1], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + WebGLGetInfo info; + switch (objectType) { + case kBuffer: + info = context->getBufferParameter(target, pname, ec); + break; + case kRenderbuffer: + info = context->getRenderbufferParameter(target, pname, ec); + break; + case kTexture: + info = context->getTexParameter(target, pname, ec); + break; + case kVertexAttrib: + // target => index + info = context->getVertexAttrib(target, pname, ec); + break; + default: + notImplemented(); + break; + } + if (ec) { + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + return toV8(info); +} + +static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok) +{ + ok = false; + WebGLUniformLocation* location = 0; + if (V8WebGLUniformLocation::HasInstance(value)) { + location = V8DOMWrapper::convertToNativeObject<WebGLUniformLocation>( + V8ClassIndex::WEBGLUNIFORMLOCATION, value->ToObject()); + ok = true; + } + return location; +} + +enum WhichProgramCall { + kProgramParameter, kUniform +}; + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetBufferParameter) +{ + INC_STATS("DOM.WebGLRenderingContext.getBufferParameter()"); + return getObjectParameter(args, kBuffer); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetFramebufferAttachmentParameter) +{ + INC_STATS("DOM.WebGLRenderingContext.getFramebufferAttachmentParameter()"); + + if (args.Length() != 3) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + ExceptionCode ec = 0; + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + bool ok; + unsigned target = toInt32(args[0], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + unsigned attachment = toInt32(args[1], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + unsigned pname = toInt32(args[2], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec); + if (ec) { + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + return toV8(info); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetParameter) +{ + INC_STATS("DOM.WebGLRenderingContext.getParameter()"); + + if (args.Length() != 1) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + ExceptionCode ec = 0; + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + bool ok; + unsigned pname = toInt32(args[0], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + WebGLGetInfo info = context->getParameter(pname, ec); + if (ec) { + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + return toV8(info); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetProgramParameter) +{ + INC_STATS("DOM.WebGLRenderingContext.getProgramParameter()"); + + if (args.Length() != 2) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + ExceptionCode ec = 0; + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? v8DOMWrapperTo<WebGLProgram>(V8ClassIndex::WEBGLPROGRAM, v8::Handle<v8::Object>::Cast(args[0])) : 0; + bool ok; + unsigned pname = toInt32(args[1], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + WebGLGetInfo info = context->getProgramParameter(program, pname, ec); + if (ec) { + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + return toV8(info); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetRenderbufferParameter) +{ + INC_STATS("DOM.WebGLRenderingContext.getRenderbufferParameter()"); + return getObjectParameter(args, kRenderbuffer); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetShaderParameter) +{ + INC_STATS("DOM.WebGLRenderingContext.getShaderParameter()"); + + if (args.Length() != 2) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + ExceptionCode ec = 0; + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? v8DOMWrapperTo<WebGLShader>(V8ClassIndex::WEBGLSHADER, v8::Handle<v8::Object>::Cast(args[0])) : 0; + bool ok; + unsigned pname = toInt32(args[1], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + WebGLGetInfo info = context->getShaderParameter(shader, pname, ec); + if (ec) { + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + return toV8(info); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetTexParameter) +{ + INC_STATS("DOM.WebGLRenderingContext.getTexParameter()"); + return getObjectParameter(args, kTexture); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetUniform) +{ + INC_STATS("DOM.WebGLRenderingContext.getUniform()"); + + if (args.Length() != 2) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + ExceptionCode ec = 0; + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? v8DOMWrapperTo<WebGLProgram>(V8ClassIndex::WEBGLPROGRAM, v8::Handle<v8::Object>::Cast(args[0])) : 0; + + bool ok = false; + WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok); + + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + WebGLGetInfo info = context->getUniform(program, location, ec); + if (ec) { + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + return toV8(info); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextGetVertexAttrib) +{ + INC_STATS("DOM.WebGLRenderingContext.getVertexAttrib()"); + return getObjectParameter(args, kVertexAttrib); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextTexImage2D) +{ + INC_STATS("DOM.WebGLRenderingContext.texImage2D()"); + + // Currently supported forms: + // * void texImage2D(in GLenum target, in GLint level, + // in GLint internalformat, + // in GLsizei width, in GLsizei height, in GLint border, + // in GLenum format, in GLenum type, in WebGLArray pixels); + // * void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, + // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha); + // * void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement image, + // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha); + if (args.Length() != 3 && + args.Length() != 4 && + args.Length() != 5 && + args.Length() != 9) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + bool ok; + int target = toInt32(args[0], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int level = toInt32(args[1], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + ExceptionCode ec = 0; + if (args.Length() == 3 || + args.Length() == 4 || + args.Length() == 5) { + v8::Handle<v8::Value> arg = args[2]; + bool flipY = false; + bool premultiplyAlpha = false; + if (args.Length() >= 4) + flipY = args[3]->BooleanValue(); + if (args.Length() >= 5) + premultiplyAlpha = args[4]->BooleanValue(); + if (V8HTMLImageElement::HasInstance(arg)) { + HTMLImageElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } else if (V8HTMLCanvasElement::HasInstance(arg)) { + HTMLCanvasElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(v8::Handle<v8::Object>::Cast(arg)); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } else { + // FIXME: support HTMLVideoElement and ImageData. + // FIXME: consider different / better exception type. + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + // Fall through + } else if (args.Length() == 9) { + int internalformat = toInt32(args[2], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int width = toInt32(args[3], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int height = toInt32(args[4], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int border = toInt32(args[5], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int format = toInt32(args[6], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int type = toInt32(args[7], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + v8::Handle<v8::Value> arg = args[8]; + if (V8WebGLArray::HasInstance(arg)) { + WebGLArray* array = V8DOMWrapper::convertToNativeObject<WebGLArray>(V8ClassIndex::WEBGLARRAY, arg->ToObject()); + // FIXME: must do validation similar to JOGL's to ensure that + // the incoming array is of the appropriate length and type + context->texImage2D(target, + level, + internalformat, + width, + height, + border, + format, + type, + array, + ec); + // Fall through + } else { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + } else { + ASSERT_NOT_REACHED(); + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + if (ec) { + V8Proxy::setDOMException(ec); + return v8::Handle<v8::Value>(); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextTexSubImage2D) +{ + INC_STATS("DOM.WebGLRenderingContext.texSubImage2D()"); + + // FIXME: implement + notImplemented(); + + return v8::Undefined(); +} + +enum FunctionToCall { + kUniform1v, kUniform2v, kUniform3v, kUniform4v, + kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v +}; + +bool isFunctionToCallForAttribute(FunctionToCall functionToCall) +{ + switch (functionToCall) { + case kVertexAttrib1v: + case kVertexAttrib2v: + case kVertexAttrib3v: + case kVertexAttrib4v: + return true; + default: + break; + } + return false; +} + +static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& args, + FunctionToCall functionToCall) { + // Forms: + // * glUniform1fv(WebGLUniformLocation location, Array data); + // * glUniform1fv(WebGLUniformLocation location, WebGLFloatArray data); + // * glUniform2fv(WebGLUniformLocation location, Array data); + // * glUniform2fv(WebGLUniformLocation location, WebGLFloatArray data); + // * glUniform3fv(WebGLUniformLocation location, Array data); + // * glUniform3fv(WebGLUniformLocation location, WebGLFloatArray data); + // * glUniform4fv(WebGLUniformLocation location, Array data); + // * glUniform4fv(WebGLUniformLocation location, WebGLFloatArray data); + // * glVertexAttrib1fv(GLint index, Array data); + // * glVertexAttrib1fv(GLint index, WebGLFloatArray data); + // * glVertexAttrib2fv(GLint index, Array data); + // * glVertexAttrib2fv(GLint index, WebGLFloatArray data); + // * glVertexAttrib3fv(GLint index, Array data); + // * glVertexAttrib3fv(GLint index, WebGLFloatArray data); + // * glVertexAttrib4fv(GLint index, Array data); + // * glVertexAttrib4fv(GLint index, WebGLFloatArray data); + + if (args.Length() != 2) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + bool ok = false; + int index = -1; + WebGLUniformLocation* location = 0; + + if (isFunctionToCallForAttribute(functionToCall)) + index = toInt32(args[0], ok); + else + location = toWebGLUniformLocation(args[0], ok); + + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + if (V8WebGLFloatArray::HasInstance(args[1])) { + WebGLFloatArray* array = + V8DOMWrapper::convertToNativeObject<WebGLFloatArray>(V8ClassIndex::WEBGLFLOATARRAY, args[1]->ToObject()); + ASSERT(array != NULL); + ExceptionCode ec = 0; + switch (functionToCall) { + case kUniform1v: context->uniform1fv(location, array, ec); break; + case kUniform2v: context->uniform2fv(location, array, ec); break; + case kUniform3v: context->uniform3fv(location, array, ec); break; + case kUniform4v: context->uniform4fv(location, array, ec); break; + case kVertexAttrib1v: context->vertexAttrib1fv(index, array); break; + case kVertexAttrib2v: context->vertexAttrib2fv(index, array); break; + case kVertexAttrib3v: context->vertexAttrib3fv(index, array); break; + case kVertexAttrib4v: context->vertexAttrib4fv(index, array); break; + default: ASSERT_NOT_REACHED(); break; + } + if (ec) + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + + v8::Handle<v8::Array> array = + v8::Local<v8::Array>::Cast(args[1]); + if (array.IsEmpty()) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + uint32_t len = array->Length(); + float* data = jsArrayToFloatArray(array, len); + if (!data) { + // FIXME: consider different / better exception type. + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + ExceptionCode ec = 0; + switch (functionToCall) { + case kUniform1v: context->uniform1fv(location, data, len, ec); break; + case kUniform2v: context->uniform2fv(location, data, len, ec); break; + case kUniform3v: context->uniform3fv(location, data, len, ec); break; + case kUniform4v: context->uniform4fv(location, data, len, ec); break; + case kVertexAttrib1v: context->vertexAttrib1fv(index, data, len); break; + case kVertexAttrib2v: context->vertexAttrib2fv(index, data, len); break; + case kVertexAttrib3v: context->vertexAttrib3fv(index, data, len); break; + case kVertexAttrib4v: context->vertexAttrib4fv(index, data, len); break; + default: ASSERT_NOT_REACHED(); break; + } + fastFree(data); + if (ec) + V8Proxy::setDOMException(ec); + return v8::Undefined(); +} + +static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args, + FunctionToCall functionToCall) { + // Forms: + // * glUniform1iv(GLUniformLocation location, Array data); + // * glUniform1iv(GLUniformLocation location, WebGLIntArray data); + // * glUniform2iv(GLUniformLocation location, Array data); + // * glUniform2iv(GLUniformLocation location, WebGLIntArray data); + // * glUniform3iv(GLUniformLocation location, Array data); + // * glUniform3iv(GLUniformLocation location, WebGLIntArray data); + // * glUniform4iv(GLUniformLocation location, Array data); + // * glUniform4iv(GLUniformLocation location, WebGLIntArray data); + + if (args.Length() != 2) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + bool ok = false; + WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); + + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + if (V8WebGLIntArray::HasInstance(args[1])) { + WebGLIntArray* array = + V8DOMWrapper::convertToNativeObject<WebGLIntArray>(V8ClassIndex::WEBGLINTARRAY, args[1]->ToObject()); + ASSERT(array != NULL); + ExceptionCode ec = 0; + switch (functionToCall) { + case kUniform1v: context->uniform1iv(location, array, ec); break; + case kUniform2v: context->uniform2iv(location, array, ec); break; + case kUniform3v: context->uniform3iv(location, array, ec); break; + case kUniform4v: context->uniform4iv(location, array, ec); break; + default: ASSERT_NOT_REACHED(); break; + } + if (ec) + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + + v8::Handle<v8::Array> array = + v8::Local<v8::Array>::Cast(args[1]); + if (array.IsEmpty()) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + uint32_t len = array->Length(); + int* data = jsArrayToIntArray(array, len); + if (!data) { + // FIXME: consider different / better exception type. + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + ExceptionCode ec = 0; + switch (functionToCall) { + case kUniform1v: context->uniform1iv(location, data, len, ec); break; + case kUniform2v: context->uniform2iv(location, data, len, ec); break; + case kUniform3v: context->uniform3iv(location, data, len, ec); break; + case kUniform4v: context->uniform4iv(location, data, len, ec); break; + default: ASSERT_NOT_REACHED(); break; + } + fastFree(data); + if (ec) + V8Proxy::setDOMException(ec); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniform1fv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniform1fv()"); + return vertexAttribAndUniformHelperf(args, kUniform1v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniform1iv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniform1iv()"); + return uniformHelperi(args, kUniform1v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniform2fv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniform2fv()"); + return vertexAttribAndUniformHelperf(args, kUniform2v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniform2iv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniform2iv()"); + return uniformHelperi(args, kUniform2v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniform3fv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniform3fv()"); + return vertexAttribAndUniformHelperf(args, kUniform3v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniform3iv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniform3iv()"); + return uniformHelperi(args, kUniform3v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniform4fv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniform4fv()"); + return vertexAttribAndUniformHelperf(args, kUniform4v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniform4iv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniform4iv()"); + return uniformHelperi(args, kUniform4v); +} + +static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args, + int matrixSize) +{ + // Forms: + // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data); + // * glUniformMatrix2fv(GLint location, GLboolean transpose, WebGLFloatArray data); + // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data); + // * glUniformMatrix3fv(GLint location, GLboolean transpose, WebGLFloatArray data); + // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data); + // * glUniformMatrix4fv(GLint location, GLboolean transpose, WebGLFloatArray data); + // + // FIXME: need to change to accept WebGLFloatArray as well. + if (args.Length() != 3) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + WebGLRenderingContext* context = + V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + + bool ok = false; + WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); + + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + bool transpose = args[1]->BooleanValue(); + if (V8WebGLFloatArray::HasInstance(args[2])) { + WebGLFloatArray* array = + V8DOMWrapper::convertToNativeObject<WebGLFloatArray>(V8ClassIndex::WEBGLFLOATARRAY, args[2]->ToObject()); + ASSERT(array != NULL); + ExceptionCode ec = 0; + switch (matrixSize) { + case 2: context->uniformMatrix2fv(location, transpose, array, ec); break; + case 3: context->uniformMatrix3fv(location, transpose, array, ec); break; + case 4: context->uniformMatrix4fv(location, transpose, array, ec); break; + default: ASSERT_NOT_REACHED(); break; + } + if (ec) + V8Proxy::setDOMException(ec); + return v8::Undefined(); + } + + v8::Handle<v8::Array> array = + v8::Local<v8::Array>::Cast(args[2]); + if (array.IsEmpty()) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + uint32_t len = array->Length(); + float* data = jsArrayToFloatArray(array, len); + if (!data) { + // FIXME: consider different / better exception type. + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + ExceptionCode ec = 0; + switch (matrixSize) { + case 2: context->uniformMatrix2fv(location, transpose, data, len, ec); break; + case 3: context->uniformMatrix3fv(location, transpose, data, len, ec); break; + case 4: context->uniformMatrix4fv(location, transpose, data, len, ec); break; + default: ASSERT_NOT_REACHED(); break; + } + fastFree(data); + if (ec) + V8Proxy::setDOMException(ec); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniformMatrix2fv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniformMatrix2fv()"); + return uniformMatrixHelper(args, 2); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniformMatrix3fv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniformMatrix3fv()"); + return uniformMatrixHelper(args, 3); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextUniformMatrix4fv) +{ + INC_STATS("DOM.WebGLRenderingContext.uniformMatrix4fv()"); + return uniformMatrixHelper(args, 4); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextVertexAttrib1fv) +{ + INC_STATS("DOM.WebGLRenderingContext.vertexAttrib1fv()"); + return vertexAttribAndUniformHelperf(args, kVertexAttrib1v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextVertexAttrib2fv) +{ + INC_STATS("DOM.WebGLRenderingContext.vertexAttrib2fv()"); + return vertexAttribAndUniformHelperf(args, kVertexAttrib2v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextVertexAttrib3fv) +{ + INC_STATS("DOM.WebGLRenderingContext.vertexAttrib3fv()"); + return vertexAttribAndUniformHelperf(args, kVertexAttrib3v); +} + +CALLBACK_FUNC_DECL(WebGLRenderingContextVertexAttrib4fv) +{ + INC_STATS("DOM.WebGLRenderingContext.vertexAttrib4fv()"); + return vertexAttribAndUniformHelperf(args, kVertexAttrib4v); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp new file mode 100644 index 0000000..f8a26c3 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" +#include "WebGLShortArray.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8WebGLArrayCustom.h" +#include "V8WebGLShortArray.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebGLShortArrayConstructor) +{ + INC_STATS("DOM.WebGLShortArray.Contructor"); + + return constructWebGLArray<WebGLShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLSHORTARRAY)); +} + +// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined". +INDEXED_PROPERTY_GETTER(WebGLShortArray) +{ + INC_STATS("DOM.WebGLShortArray.IndexedPropertyGetter"); + WebGLShortArray* array = V8DOMWrapper::convertToNativeObject<WebGLShortArray>(V8ClassIndex::WEBGLSHORTARRAY, info.Holder()); + + if ((index < 0) || (index >= array->length())) + return v8::Undefined(); + short result; + if (!array->get(index, result)) + return v8::Undefined(); + return v8::Number::New(result); +} + +// Set the specified value in the array. Accesses outside the valid array range are silently ignored. +INDEXED_PROPERTY_SETTER(WebGLShortArray) +{ + INC_STATS("DOM.WebGLShortArray.IndexedPropertySetter"); + WebGLShortArray* array = V8DOMWrapper::convertToNativeObject<WebGLShortArray>(V8ClassIndex::WEBGLSHORTARRAY, info.Holder()); + + if ((index >= 0) && (index < array->length())) { + if (!value->IsNumber()) + return throwError("Could not convert value argument to a number"); + array->set(index, value->NumberValue()); + } + return value; +} + +CALLBACK_FUNC_DECL(WebGLShortArrayGet) +{ + INC_STATS("DOM.WebGLShortArray.get()"); + return getWebGLArrayElement<WebGLShortArray, short>(args, V8ClassIndex::WEBGLSHORTARRAY); +} + +CALLBACK_FUNC_DECL(WebGLShortArraySet) +{ + INC_STATS("DOM.WebGLShortArray.set()"); + return setWebGLArray<WebGLShortArray, V8WebGLShortArray>(args, V8ClassIndex::WEBGLSHORTARRAY); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp new file mode 100644 index 0000000..391f213 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" +#include "WebGLUnsignedByteArray.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8WebGLArrayCustom.h" +#include "V8WebGLUnsignedByteArray.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebGLUnsignedByteArrayConstructor) +{ + INC_STATS("DOM.WebGLUnsignedByteArray.Contructor"); + + return constructWebGLArray<WebGLUnsignedByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY)); +} + +// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined". +INDEXED_PROPERTY_GETTER(WebGLUnsignedByteArray) +{ + INC_STATS("DOM.WebGLUnsignedByteArray.IndexedPropertyGetter"); + WebGLUnsignedByteArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedByteArray>(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY, info.Holder()); + + if ((index < 0) || (index >= array->length())) + return v8::Undefined(); + unsigned char result; + if (!array->get(index, result)) + return v8::Undefined(); + return v8::Number::New(result); +} + +// Set the specified value in the array. Accesses outside the valid array range are silently ignored. +INDEXED_PROPERTY_SETTER(WebGLUnsignedByteArray) +{ + INC_STATS("DOM.WebGLUnsignedByteArray.IndexedPropertySetter"); + WebGLUnsignedByteArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedByteArray>(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY, info.Holder()); + + if ((index >= 0) && (index < array->length())) { + if (!value->IsNumber()) + return throwError("Could not convert value argument to a number"); + array->set(index, value->NumberValue()); + } + return value; +} + +CALLBACK_FUNC_DECL(WebGLUnsignedByteArrayGet) +{ + INC_STATS("DOM.WebGLUnsignedByteArray.get()"); + return getWebGLArrayElement<WebGLUnsignedByteArray, unsigned char>(args, V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY); +} + +CALLBACK_FUNC_DECL(WebGLUnsignedByteArraySet) +{ + INC_STATS("DOM.WebGLUnsignedByteArray.set()"); + return setWebGLArray<WebGLUnsignedByteArray, V8WebGLUnsignedByteArray>(args, V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp new file mode 100644 index 0000000..92b9fe0 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" +#include "WebGLUnsignedIntArray.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8WebGLArrayCustom.h" +#include "V8WebGLUnsignedIntArray.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebGLUnsignedIntArrayConstructor) +{ + INC_STATS("DOM.WebGLUnsignedIntArray.Contructor"); + + return constructWebGLArray<WebGLUnsignedIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDINTARRAY)); +} + +// Get the specified value from the integer array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid pixel buffer range return "undefined". +INDEXED_PROPERTY_GETTER(WebGLUnsignedIntArray) +{ + INC_STATS("DOM.WebGLUnsignedIntArray.IndexedPropertyGetter"); + WebGLUnsignedIntArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedIntArray>(V8ClassIndex::WEBGLUNSIGNEDINTARRAY, info.Holder()); + + if ((index < 0) || (index >= array->length())) + return v8::Undefined(); + unsigned int result; + if (!array->get(index, result)) + return v8::Undefined(); + return v8::Number::New(result); +} + +// Set the specified value in the integer array. Accesses outside the valid integer array range are silently ignored. +INDEXED_PROPERTY_SETTER(WebGLUnsignedIntArray) +{ + INC_STATS("DOM.WebGLUnsignedIntArray.IndexedPropertySetter"); + WebGLUnsignedIntArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedIntArray>(V8ClassIndex::WEBGLUNSIGNEDINTARRAY, info.Holder()); + + if ((index >= 0) && (index < array->length())) { + if (!value->IsNumber()) + return throwError("Could not convert value argument to a number"); + array->set(index, value->NumberValue()); + } + return value; +} + +CALLBACK_FUNC_DECL(WebGLUnsignedIntArrayGet) +{ + INC_STATS("DOM.WebGLUnsignedIntArray.get()"); + return getWebGLArrayElement<WebGLUnsignedIntArray, unsigned int>(args, V8ClassIndex::WEBGLUNSIGNEDINTARRAY); +} + +CALLBACK_FUNC_DECL(WebGLUnsignedIntArraySet) +{ + INC_STATS("DOM.WebGLUnsignedIntArray.set()"); + return setWebGLArray<WebGLUnsignedIntArray, V8WebGLUnsignedIntArray>(args, V8ClassIndex::WEBGLUNSIGNEDINTARRAY); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp new file mode 100644 index 0000000..ce261e9 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "WebGLArrayBuffer.h" +#include "WebGLUnsignedShortArray.h" + +#include "V8Binding.h" +#include "V8WebGLArrayBuffer.h" +#include "V8WebGLArrayCustom.h" +#include "V8WebGLUnsignedShortArray.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebGLUnsignedShortArrayConstructor) +{ + INC_STATS("DOM.WebGLUnsignedShortArray.Contructor"); + + return constructWebGLArray<WebGLUnsignedShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY)); +} + +// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined". +INDEXED_PROPERTY_GETTER(WebGLUnsignedShortArray) +{ + INC_STATS("DOM.WebGLUnsignedShortArray.IndexedPropertyGetter"); + WebGLUnsignedShortArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedShortArray>(V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY, info.Holder()); + + if ((index < 0) || (index >= array->length())) + return v8::Undefined(); + unsigned short result; + if (!array->get(index, result)) + return v8::Undefined(); + return v8::Number::New(result); +} + +// Set the specified value in the array. Accesses outside the valid array range are silently ignored. +INDEXED_PROPERTY_SETTER(WebGLUnsignedShortArray) +{ + INC_STATS("DOM.WebGLUnsignedShortArray.IndexedPropertySetter"); + WebGLUnsignedShortArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedShortArray>(V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY, info.Holder()); + + if ((index >= 0) && (index < array->length())) { + if (!value->IsNumber()) + return throwError("Could not convert value argument to a number"); + array->set(index, value->NumberValue()); + } + return value; +} + +CALLBACK_FUNC_DECL(WebGLUnsignedShortArrayGet) +{ + INC_STATS("DOM.WebGLUnsignedShortArray.get()"); + return getWebGLArrayElement<WebGLUnsignedShortArray, unsigned short>(args, V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY); +} + +CALLBACK_FUNC_DECL(WebGLUnsignedShortArraySet) +{ + INC_STATS("DOM.WebGLUnsignedShortArray.set()"); + return setWebGLArray<WebGLUnsignedShortArray, V8WebGLUnsignedShortArray>(args, V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY); +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp index dd19a88..b2a807d 100755 --- a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp @@ -30,17 +30,38 @@ #include "config.h" +#include "V8Binding.h" #include "V8CustomBinding.h" +#include "V8DOMWrapper.h" #include "V8Index.h" #include "V8Proxy.h" #include "WebKitPoint.h" +#include <wtf/MathExtras.h> + namespace WebCore { CALLBACK_FUNC_DECL(WebKitPointConstructor) { INC_STATS("DOM.WebKitPoint.Constructor"); - return V8Proxy::constructDOMObject<V8ClassIndex::WEBKITPOINT, WebKitPoint>(args); + float x = 0; + float y = 0; + if (args.Length() > 1) { + if (!args[0]->IsUndefined()) { + x = toFloat(args[0]); + if (isnan(x)) + x = 0; + } + if (!args[1]->IsUndefined()) { + y = toFloat(args[1]); + if (isnan(y)) + y = 0; + } + } + PassRefPtr<WebKitPoint> point = WebKitPoint::create(x, y); + point->ref(); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::WEBKITPOINT, point.get()); + return args.Holder(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp new file mode 100644 index 0000000..b20635b --- /dev/null +++ b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEB_SOCKETS) + +#include "WebSocket.h" + +#include "Frame.h" +#include "Settings.h" +#include "V8Binding.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WebSocketAddEventListener) +{ + INC_STATS("DOM.WebSocket.addEventListener()"); + WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder()); + + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(webSocket, args[1], false, ListenerFindOrCreate); + if (listener) { + String type = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + webSocket->addEventListener(type, listener, useCapture); + + createHiddenDependency(args.Holder(), args[1], V8Custom::kWebSocketCacheIndex); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(WebSocketRemoveEventListener) +{ + INC_STATS("DOM.WebSocket.removeEventListener()"); + WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder()); + + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(webSocket, args[1], false, ListenerFindOnly); + if (listener) { + String type = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + webSocket->removeEventListener(type, listener.get(), useCapture); + removeHiddenDependency(args.Holder(), args[1], V8Custom::kWebSocketCacheIndex); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(WebSocketConstructor) +{ + INC_STATS("DOM.WebSocket.Constructor"); + + if (!args.IsConstructCall()) + return throwError("DOM object custructor cannot be called as a function."); + if (args.Length() == 0) + return throwError("Not enough arguments", V8Proxy::SyntaxError); + + v8::TryCatch tryCatch; + v8::Handle<v8::String> urlstring = args[0]->ToString(); + if (tryCatch.HasCaught()) + return throwError(tryCatch.Exception()); + if (urlstring.IsEmpty()) + return throwError("Empty URL", V8Proxy::SyntaxError); + + // Get the script execution context. + ScriptExecutionContext* context = 0; + // TODO: Workers + if (!context) { + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("WebSocket constructor's associated frame is not available", V8Proxy::ReferenceError); + context = frame->document(); + } + + const KURL& url = context->completeURL(toWebCoreString(urlstring)); + + RefPtr<WebSocket> webSocket = WebSocket::create(context); + ExceptionCode ec = 0; + + if (args.Length() < 2) + webSocket->connect(url, ec); + else { + v8::TryCatch tryCatchProtocol; + v8::Handle<v8::String> protocol = args[1]->ToString(); + if (tryCatchProtocol.HasCaught()) + return throwError(tryCatchProtocol.Exception()); + webSocket->connect(url, toWebCoreString(protocol), ec); + } + if (ec) + return throwError(ec); + + // Setup the standard wrapper object internal fields. + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBSOCKET), webSocket.get()); + + // Add object to the wrapper map. + webSocket->ref(); + V8DOMWrapper::setJSWrapperForActiveDOMObject(webSocket.get(), v8::Persistent<v8::Object>::New(args.Holder())); + + return args.Holder(); +} + +CALLBACK_FUNC_DECL(WebSocketSend) +{ + INC_STATS("DOM.WebSocket.send()"); + WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder()); + + ExceptionCode ec = 0; + bool ret = false; + if (args.Length() < 1) + return throwError("Not enough arguments", V8Proxy::SyntaxError); + else { + String msg = toWebCoreString(args[0]); + ret = webSocket->send(msg, ec); + } + if (ec) + return throwError(ec); + return v8Boolean(ret); +} + +CALLBACK_FUNC_DECL(WebSocketClose) +{ + INC_STATS("DOM.WebSocket.close()"); + WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder()); + + webSocket->close(); + return v8::Undefined(); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_SOCKETS) diff --git a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp index b526040..9b68ac0 100755 --- a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp @@ -34,6 +34,7 @@ #include "DOMTimer.h" #include "ExceptionCode.h" +#include "RuntimeEnabledFeatures.h" #include "ScheduledAction.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -45,6 +46,13 @@ namespace WebCore { +#if ENABLE(NOTIFICATIONS) +ACCESSOR_RUNTIME_ENABLER(WorkerContextWebkitNotifications) +{ + return RuntimeEnabledFeatures::notificationsEnabled(); +} +#endif + ACCESSOR_GETTER(WorkerContextSelf) { INC_STATS(L"DOM.WorkerContext.self._get"); @@ -52,45 +60,6 @@ ACCESSOR_GETTER(WorkerContextSelf) return WorkerContextExecutionProxy::convertWorkerContextToV8Object(workerContext); } -ACCESSOR_GETTER(WorkerContextOnerror) -{ - INC_STATS(L"DOM.WorkerContext.onerror._get"); - WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - if (workerContext->onerror()) { - V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onerror()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(WorkerContextOnerror) -{ - INC_STATS(L"DOM.WorkerContext.onerror._set"); - WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onerror()); - if (value->IsNull()) { - if (workerContext->onerror()) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex); - } - - // Clear the listener. - workerContext->setOnerror(0); - } else { - RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), true, false); - if (listener) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex); - } - - workerContext->setOnerror(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kWorkerContextRequestCacheIndex); - } - } -} - v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singleShot) { WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); @@ -103,9 +72,10 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl int32_t timeout = argumentCount >= 2 ? args[1]->Int32Value() : 0; int timerId; + v8::Handle<v8::Context> v8Context = workerContext->script()->proxy()->context(); if (function->IsString()) { WebCore::String stringFunction = toWebCoreString(function); - timerId = DOMTimer::install(workerContext, new ScheduledAction(stringFunction, workerContext->url()), timeout, singleShot); + timerId = DOMTimer::install(workerContext, new ScheduledAction(v8Context, stringFunction, workerContext->url()), timeout, singleShot); } else if (function->IsFunction()) { size_t paramCount = argumentCount >= 2 ? argumentCount - 2 : 0; v8::Local<v8::Value>* params = 0; @@ -115,7 +85,7 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl params[i] = args[i+2]; } // ScheduledAction takes ownership of actual params and releases them in its destructor. - ScheduledAction* action = new ScheduledAction(v8::Handle<v8::Function>::Cast(function), paramCount, params); + ScheduledAction* action = new ScheduledAction(v8Context, v8::Handle<v8::Function>::Cast(function), paramCount, params); delete [] params; timerId = DOMTimer::install(workerContext, action, timeout, singleShot); } else @@ -130,8 +100,13 @@ CALLBACK_FUNC_DECL(WorkerContextImportScripts) if (!args.Length()) return v8::Undefined(); - String callerURL = V8Proxy::sourceName(); - int callerLine = V8Proxy::sourceLineNumber() + 1; + String callerURL; + if (!V8Proxy::sourceName(callerURL)) + return v8::Undefined(); + int callerLine; + if (!V8Proxy::sourceLineNumber(callerLine)) + return v8::Undefined(); + callerLine += 1; Vector<String> urls; for (int i = 0; i < args.Length(); i++) { @@ -170,8 +145,7 @@ CALLBACK_FUNC_DECL(WorkerContextAddEventListener) INC_STATS(L"DOM.WorkerContext.addEventListener()"); WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); - RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, false); - + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOrCreate); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -186,10 +160,8 @@ CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener) { INC_STATS(L"DOM.WorkerContext.removeEventListener()"); WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); - WorkerContextExecutionProxy* proxy = workerContext->script()->proxy(); - - RefPtr<V8EventListener> listener = proxy->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, true); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOnly); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -197,7 +169,6 @@ CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener) removeHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerContextRequestCacheIndex); } - return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp index 32450b8..454e41f 100755 --- a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp @@ -36,9 +36,10 @@ #include "ExceptionCode.h" #include "Frame.h" +#include "SerializedScriptValue.h" #include "V8Binding.h" #include "V8CustomBinding.h" -#include "V8ObjectEventListener.h" +#include "V8MessagePortCustom.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContext.h" @@ -65,16 +66,9 @@ CALLBACK_FUNC_DECL(WorkerConstructor) return v8::Undefined(); // Get the script execution context. - ScriptExecutionContext* context = 0; - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); - if (proxy) - context = proxy->workerContext(); - else { - Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); - if (!frame) - return v8::Undefined(); - context = frame->document(); - } + ScriptExecutionContext* context = getScriptExecutionContext(); + if (!context) + return v8::Undefined(); // Create the worker object. // Note: it's OK to let this RefPtr go out of scope because we also call setDOMWrapper(), which effectively holds a reference to obj. @@ -93,60 +87,19 @@ CALLBACK_FUNC_DECL(WorkerConstructor) return wrapperObject; } -PassRefPtr<EventListener> getEventListener(Worker* worker, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) -{ - if (worker->scriptExecutionContext()->isWorkerContext()) { - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - ASSERT(workerContextProxy); - return workerContextProxy->findOrCreateObjectEventListener(value, isAttribute, findOnly); - } - - V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext()); - if (proxy) { - V8EventListenerList* list = proxy->objectListeners(); - return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); - } - - return 0; -} - -ACCESSOR_GETTER(WorkerOnmessage) -{ - INC_STATS(L"DOM.Worker.onmessage._get"); - Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); - if (worker->onmessage()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onmessage()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(WorkerOnmessage) +CALLBACK_FUNC_DECL(WorkerPostMessage) { - INC_STATS(L"DOM.Worker.onmessage._set"); - Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); - V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onmessage()); - if (value->IsNull()) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex); - } - - // Clear the listener. - worker->setOnmessage(0); - } else { - RefPtr<EventListener> listener = getEventListener(worker, value, true, false); - if (listener) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex); - } - - worker->setOnmessage(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kWorkerRequestCacheIndex); - } + INC_STATS("DOM.Worker.postMessage"); + Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder()); + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0])); + MessagePortArray portArray; + if (args.Length() > 1) { + if (!getMessagePortArray(args[1], portArray)) + return v8::Undefined(); } + ExceptionCode ec = 0; + worker->postMessage(message.release(), &portArray, ec); + return throwError(ec); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp index 02ce8e2..af647cd 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp @@ -33,8 +33,8 @@ #include "Frame.h" #include "V8Binding.h" #include "V8CustomBinding.h" -#include "V8ObjectEventListener.h" #include "V8Proxy.h" +#include "V8Utilities.h" #include "XMLHttpRequest.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" @@ -50,20 +50,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) // Expect no parameters. // Allocate a XMLHttpRequest object as its internal field. - ScriptExecutionContext* context = 0; -#if ENABLE(WORKERS) - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); - if (proxy) - context = proxy->workerContext(); - else { -#endif - Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); - if (!frame) - return throwError("XMLHttpRequest constructor's associated frame is not available", V8Proxy::ReferenceError); - context = frame->document(); -#if ENABLE(WORKERS) - } -#endif + ScriptExecutionContext* context = getScriptExecutionContext(); + if (!context) + return throwError("XMLHttpRequest constructor's associated context is not available", V8Proxy::ReferenceError); RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context); V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xmlHttpRequest.get()); diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp index 7204a61..c3e4645 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp @@ -33,10 +33,10 @@ #include "Frame.h" #include "V8Binding.h" -#include "V8Document.h" #include "V8CustomBinding.h" +#include "V8Document.h" +#include "V8File.h" #include "V8HTMLDocument.h" -#include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContext.h" @@ -44,234 +44,11 @@ namespace WebCore { -static PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::Local<v8::Value> value, bool findOnly) -{ -#if ENABLE(WORKERS) - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) - return workerContextProxy->findOrCreateObjectEventListener(value, false, findOnly); -#endif - - V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (proxy) { - V8EventListenerList* list = proxy->objectListeners(); - return findOnly ? list->findWrapper(value, false) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); - } - - return PassRefPtr<EventListener>(); -} - -ACCESSOR_GETTER(XMLHttpRequestOnabort) -{ - INC_STATS("DOM.XMLHttpRequest.onabort._get"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (xmlHttpRequest->onabort()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onabort()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestOnabort) -{ - INC_STATS("DOM.XMLHttpRequest.onabort._set"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequest->onabort()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onabort()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequest->setOnabort(0); - } else { - RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false); - if (listener) { - xmlHttpRequest->setOnabort(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestOnerror) -{ - INC_STATS("DOM.XMLHttpRequest.onerror._get"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (xmlHttpRequest->onerror()) { - RefPtr<V8ObjectEventListener> listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onerror()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestOnerror) -{ - INC_STATS("DOM.XMLHttpRequest.onerror._set"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequest->onerror()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onerror()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequest->setOnerror(0); - } else { - RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false); - if (listener) { - xmlHttpRequest->setOnerror(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestOnload) -{ - INC_STATS("DOM.XMLHttpRequest.onload._get"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (xmlHttpRequest->onload()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onload()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestOnload) -{ - INC_STATS("DOM.XMLHttpRequest.onload._set"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequest->onload()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onload()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - xmlHttpRequest->setOnload(0); - - } else { - RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false); - if (listener) { - xmlHttpRequest->setOnload(listener.get()); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestOnloadstart) -{ - INC_STATS("DOM.XMLHttpRequest.onloadstart._get"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (xmlHttpRequest->onloadstart()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onloadstart()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestOnloadstart) -{ - INC_STATS("DOM.XMLHttpRequest.onloadstart._set"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequest->onloadstart()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onloadstart()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequest->setOnloadstart(0); - } else { - RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false); - if (listener) { - xmlHttpRequest->setOnloadstart(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestOnprogress) -{ - INC_STATS("DOM.XMLHttpRequest.onprogress._get"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (xmlHttpRequest->onprogress()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onprogress()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestOnprogress) -{ - INC_STATS("DOM.XMLHttpRequest.onprogress._set"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequest->onprogress()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onprogress()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequest->setOnprogress(0); - } else { - RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false); - if (listener) { - xmlHttpRequest->setOnprogress(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestOnreadystatechange) -{ - INC_STATS("DOM.XMLHttpRequest.onreadystatechange._get"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (xmlHttpRequest->onreadystatechange()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onreadystatechange()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestOnreadystatechange) -{ - INC_STATS("DOM.XMLHttpRequest.onreadystatechange._set"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequest->onreadystatechange()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onreadystatechange()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequest->setOnreadystatechange(0); - } else { - RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false); - if (listener) { - xmlHttpRequest->setOnreadystatechange(listener.get()); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - ACCESSOR_GETTER(XMLHttpRequestResponseText) { - // FIXME: This is only needed because webkit set this getter as custom. - // So we need a custom method to avoid forking the IDL file. INC_STATS("DOM.XMLHttpRequest.responsetext._get"); XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - return v8StringOrNull(xmlHttpRequest->responseText()); + return xmlHttpRequest->responseText().v8StringOrNull(); } CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) @@ -279,7 +56,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) INC_STATS("DOM.XMLHttpRequest.addEventListener()"); XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, args[1], false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -295,7 +72,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestRemoveEventListener) INC_STATS("DOM.XMLHttpRequest.removeEventListener()"); XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, args[1], true); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -323,22 +100,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOpen) String method = toWebCoreString(args[0]); String urlstring = toWebCoreString(args[1]); - ScriptExecutionContext* context = 0; -#if ENABLE(WORKERS) - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) { - context = workerContextProxy->workerContext(); - ASSERT(context); - } -#endif - - if (!context) { - V8Proxy* proxy = V8Proxy::retrieve(); - if (!proxy) - return v8::Undefined(); - context = proxy->frame()->document(); - ASSERT(context); - } + ScriptExecutionContext* context = getScriptExecutionContext(); + if (!context) + return v8::Undefined(); KURL url = context->completeURL(urlstring); @@ -379,12 +143,16 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSend) xmlHttpRequest->send(ec); else { v8::Handle<v8::Value> arg = args[0]; - // FIXME: upstream handles "File" objects too. if (IsDocumentType(arg)) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); Document* document = V8DOMWrapper::convertDOMWrapperToNode<Document>(object); ASSERT(document); xmlHttpRequest->send(document, ec); + } else if (V8File::HasInstance(arg)) { + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); + File* file = V8DOMWrapper::convertDOMWrapperToNative<File>(object); + ASSERT(file); + xmlHttpRequest->send(file, ec); } else xmlHttpRequest->send(toWebCoreStringWithNullCheck(arg), ec); } diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp index bbc69dd..9323f71 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp @@ -34,7 +34,6 @@ #include "ExceptionCode.h" #include "V8Binding.h" #include "V8CustomBinding.h" -#include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "XMLHttpRequest.h" @@ -43,212 +42,14 @@ namespace WebCore { -ACCESSOR_GETTER(XMLHttpRequestUploadOnabort) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onabort._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (xmlHttpRequestUpload->onabort()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onabort()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestUploadOnabort) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onabort._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequestUpload->onabort()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onabort()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequestUpload->setOnabort(0); - } else { - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); - if (listener) { - xmlHttpRequestUpload->setOnabort(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestUploadOnerror) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onerror._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (xmlHttpRequestUpload->onerror()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onerror()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestUploadOnerror) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onerror._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequestUpload->onerror()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onerror()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequestUpload->setOnerror(0); - } else { - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); - if (listener) { - xmlHttpRequestUpload->setOnerror(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestUploadOnload) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onload._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (xmlHttpRequestUpload->onload()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onload()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestUploadOnload) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onload._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequestUpload->onload()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onload()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequestUpload->setOnload(0); - } else { - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); - if (listener) { - xmlHttpRequestUpload->setOnload(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestUploadOnloadstart) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onloadstart._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (xmlHttpRequestUpload->onloadstart()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onloadstart()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onloadstart._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequestUpload->onloadstart()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onloadstart()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequestUpload->setOnloadstart(0); - } else { - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); - if (listener) { - xmlHttpRequestUpload->setOnloadstart(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - -ACCESSOR_GETTER(XMLHttpRequestUploadOnprogress) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onprogress._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (xmlHttpRequestUpload->onprogress()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onprogress()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Null(); -} - -ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress) -{ - INC_STATS("DOM.XMLHttpRequestUpload.onprogress._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); - if (value->IsNull()) { - if (xmlHttpRequestUpload->onprogress()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onprogress()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - xmlHttpRequestUpload->setOnprogress(0); - } else { - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); - if (listener) { - xmlHttpRequestUpload->setOnprogress(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); - } - } -} - CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener) { INC_STATS("DOM.XMLHttpRequestUpload.addEventListener()"); XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), args[1], false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -265,12 +66,8 @@ CALLBACK_FUNC_DECL(XMLHttpRequestUploadRemoveEventListener) XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); // Probably leaked. - - RefPtr<EventListener> listener = proxy->objectListeners()->findWrapper(args[1], false); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); diff --git a/WebCore/bindings/v8/npruntime.cpp b/WebCore/bindings/v8/npruntime.cpp index 64a1927..35015b0 100644 --- a/WebCore/bindings/v8/npruntime.cpp +++ b/WebCore/bindings/v8/npruntime.cpp @@ -39,7 +39,7 @@ // The static initializer here should work okay, but we want to avoid // static initialization in general. -namespace { +namespace npruntime { // We use StringKey here as the key-type to avoid a string copy to // construct the map key and for faster comparisons than strcmp. @@ -112,7 +112,10 @@ struct StringKeyHash { static const bool safeToCompareToEmptyOrDeleted = true; }; -} // namespace +} // namespace npruntime + +using npruntime::StringKey; +using npruntime::StringKeyHash; // Implement HashTraits<StringKey> struct StringKeyHashTraits : WTF::GenericHashTraits<StringKey> { @@ -309,6 +312,15 @@ void _NPN_DeallocateObject(NPObject* npObject) } } +#if PLATFORM(ANDROID) +// Android uses NPN_ReleaseObject (the 'public' version of _NPN_ReleaseObject) +// in WebCoreFrameBridge.cpp. See http://trac.webkit.org/changeset/47021. +// TODO: Upstream this to webkit.org. +void NPN_ReleaseObject(NPObject *obj) +{ + _NPN_ReleaseObject(obj); +} +#endif void _NPN_ReleaseObject(NPObject* npObject) { ASSERT(npObject); |
