summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/bindings
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-06-02 12:07:03 +0100
committerBen Murdoch <benm@google.com>2011-06-10 10:47:21 +0100
commit2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch)
treee4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebCore/bindings
parent87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff)
downloadexternal_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip
external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz
external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebCore/bindings')
-rw-r--r--Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp4
-rw-r--r--Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h9
-rw-r--r--Source/WebCore/bindings/js/CallbackFunction.cpp51
-rw-r--r--Source/WebCore/bindings/js/CallbackFunction.h58
-rw-r--r--Source/WebCore/bindings/js/DOMWrapperWorld.cpp14
-rw-r--r--Source/WebCore/bindings/js/DOMWrapperWorld.h41
-rw-r--r--Source/WebCore/bindings/js/GCController.cpp19
-rw-r--r--Source/WebCore/bindings/js/JSArrayBufferViewHelper.h4
-rw-r--r--Source/WebCore/bindings/js/JSAttrCustom.cpp8
-rw-r--r--Source/WebCore/bindings/js/JSAudioConstructor.h2
-rw-r--r--Source/WebCore/bindings/js/JSAudioContextCustom.cpp24
-rw-r--r--Source/WebCore/bindings/js/JSBindingsAllInOne.cpp1
-rw-r--r--Source/WebCore/bindings/js/JSCSSRuleCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp30
-rw-r--r--Source/WebCore/bindings/js/JSCSSValueCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSCallbackData.h6
-rw-r--r--Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp4
-rw-r--r--Source/WebCore/bindings/js/JSCustomVoidCallback.h2
-rw-r--r--Source/WebCore/bindings/js/JSDOMBinding.cpp222
-rw-r--r--Source/WebCore/bindings/js/JSDOMBinding.h104
-rw-r--r--Source/WebCore/bindings/js/JSDOMGlobalObject.cpp6
-rw-r--r--Source/WebCore/bindings/js/JSDOMGlobalObject.h6
-rw-r--r--Source/WebCore/bindings/js/JSDOMImplementationCustom.cpp8
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowBase.cpp4
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowBase.h6
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowCustom.cpp21
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowShell.cpp10
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowShell.h4
-rw-r--r--Source/WebCore/bindings/js/JSDOMWrapper.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSDOMWrapper.h7
-rw-r--r--Source/WebCore/bindings/js/JSDataGridDataSource.h2
-rw-r--r--Source/WebCore/bindings/js/JSDataViewCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSDirectoryEntryCustom.cpp18
-rw-r--r--Source/WebCore/bindings/js/JSDirectoryEntrySyncCustom.cpp14
-rw-r--r--Source/WebCore/bindings/js/JSDocumentCustom.cpp8
-rw-r--r--Source/WebCore/bindings/js/JSElementCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSEventCustom.cpp6
-rw-r--r--Source/WebCore/bindings/js/JSEventListener.cpp17
-rw-r--r--Source/WebCore/bindings/js/JSEventListener.h4
-rw-r--r--Source/WebCore/bindings/js/JSEventTarget.cpp4
-rw-r--r--Source/WebCore/bindings/js/JSGeolocationCustom.cpp41
-rw-r--r--Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSImageConstructor.h2
-rw-r--r--Source/WebCore/bindings/js/JSImageDataCustom.cpp6
-rw-r--r--Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp1
-rw-r--r--Source/WebCore/bindings/js/JSInjectedScriptManager.cpp6
-rw-r--r--Source/WebCore/bindings/js/JSMessageEventCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp52
-rw-r--r--Source/WebCore/bindings/js/JSNavigatorCustom.cpp30
-rw-r--r--Source/WebCore/bindings/js/JSNodeCustom.cpp156
-rw-r--r--Source/WebCore/bindings/js/JSNodeCustom.h57
-rw-r--r--Source/WebCore/bindings/js/JSNodeFilterCondition.cpp18
-rw-r--r--Source/WebCore/bindings/js/JSNodeFilterCondition.h15
-rw-r--r--Source/WebCore/bindings/js/JSNodeFilterCustom.cpp8
-rw-r--r--Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSNodeListCustom.cpp39
-rw-r--r--Source/WebCore/bindings/js/JSOptionConstructor.h2
-rw-r--r--Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp5
-rw-r--r--Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSStyleSheetCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp2
-rw-r--r--Source/WebCore/bindings/js/JSWorkerContextBase.cpp5
-rw-r--r--Source/WebCore/bindings/js/JSWorkerContextBase.h4
-rw-r--r--Source/WebCore/bindings/js/JSWorkerContextCustom.cpp6
-rw-r--r--Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp8
-rw-r--r--Source/WebCore/bindings/js/ScheduledAction.cpp7
-rw-r--r--Source/WebCore/bindings/js/ScheduledAction.h9
-rw-r--r--Source/WebCore/bindings/js/ScriptCachedFrameData.cpp2
-rw-r--r--Source/WebCore/bindings/js/ScriptCachedFrameData.h5
-rw-r--r--Source/WebCore/bindings/js/ScriptController.cpp4
-rw-r--r--Source/WebCore/bindings/js/ScriptController.h4
-rw-r--r--Source/WebCore/bindings/js/ScriptDebugServer.cpp20
-rw-r--r--Source/WebCore/bindings/js/ScriptDebugServer.h4
-rw-r--r--Source/WebCore/bindings/js/ScriptGCEvent.cpp2
-rw-r--r--Source/WebCore/bindings/js/ScriptObject.h2
-rw-r--r--Source/WebCore/bindings/js/ScriptState.cpp12
-rw-r--r--Source/WebCore/bindings/js/ScriptState.h11
-rw-r--r--Source/WebCore/bindings/js/ScriptValue.cpp20
-rw-r--r--Source/WebCore/bindings/js/ScriptValue.h17
-rw-r--r--Source/WebCore/bindings/js/ScriptWrappable.h15
-rw-r--r--Source/WebCore/bindings/js/SerializedScriptValue.cpp144
-rw-r--r--Source/WebCore/bindings/js/SerializedScriptValue.h26
-rw-r--r--Source/WebCore/bindings/js/WorkerScriptController.cpp69
-rw-r--r--Source/WebCore/bindings/js/WorkerScriptController.h20
-rw-r--r--Source/WebCore/bindings/scripts/CodeGeneratorJS.pm72
-rw-r--r--Source/WebCore/bindings/scripts/CodeGeneratorV8.pm6
-rw-r--r--Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp1
-rw-r--r--Source/WebCore/bindings/v8/DebuggerScript.js30
-rw-r--r--Source/WebCore/bindings/v8/ScriptDebugServer.cpp12
-rw-r--r--Source/WebCore/bindings/v8/ScriptDebugServer.h2
-rw-r--r--Source/WebCore/bindings/v8/ScriptState.cpp19
-rw-r--r--Source/WebCore/bindings/v8/ScriptState.h7
-rw-r--r--Source/WebCore/bindings/v8/ScriptValue.cpp9
-rw-r--r--Source/WebCore/bindings/v8/V8AbstractEventListener.cpp10
-rw-r--r--Source/WebCore/bindings/v8/V8DOMWrapper.cpp3
-rw-r--r--Source/WebCore/bindings/v8/V8GCController.cpp18
-rw-r--r--Source/WebCore/bindings/v8/V8Utilities.cpp5
-rw-r--r--Source/WebCore/bindings/v8/V8Utilities.h30
-rw-r--r--Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp7
-rw-r--r--Source/WebCore/bindings/v8/WorkerScriptController.cpp25
-rw-r--r--Source/WebCore/bindings/v8/WorkerScriptController.h18
-rwxr-xr-xSource/WebCore/bindings/v8/WorkerScriptDebugServer.cpp101
-rwxr-xr-xSource/WebCore/bindings/v8/WorkerScriptDebugServer.h10
-rw-r--r--Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp29
-rw-r--r--Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp20
-rw-r--r--Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp3
-rw-r--r--Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp18
-rw-r--r--Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp14
-rw-r--r--Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp28
-rw-r--r--Source/WebCore/bindings/v8/custom/V8EventCustom.cpp3
-rw-r--r--Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp51
-rw-r--r--Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp6
-rw-r--r--Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp65
114 files changed, 1376 insertions, 872 deletions
diff --git a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp
index e9591fd..dd47184 100644
--- a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp
+++ b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp
@@ -142,4 +142,8 @@ bool RuntimeEnabledFeatures::openDatabaseSyncEnabled()
}
#endif
+#if ENABLE(QUOTA)
+bool RuntimeEnabledFeatures::isQuotaEnabled = false;
+#endif
+
} // namespace WebCore
diff --git a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h
index 1004ea4..3432d74 100644
--- a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h
+++ b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h
@@ -150,6 +150,11 @@ public:
static bool webkitGetUserMediaEnabled() { return isMediaStreamEnabled; }
#endif
+#if ENABLE(QUOTA)
+ static bool quotaEnabled() { return isQuotaEnabled; }
+ static void setQuotaEnabled(bool isEnabled) { isQuotaEnabled = isEnabled; }
+#endif
+
private:
// Never instantiate.
RuntimeEnabledFeatures() { }
@@ -182,6 +187,10 @@ private:
#if ENABLE(MEDIA_STREAM)
static bool isMediaStreamEnabled;
#endif
+
+#if ENABLE(QUOTA)
+ static bool isQuotaEnabled;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/CallbackFunction.cpp b/Source/WebCore/bindings/js/CallbackFunction.cpp
new file mode 100644
index 0000000..145d055
--- /dev/null
+++ b/Source/WebCore/bindings/js/CallbackFunction.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "CallbackFunction.h"
+
+#include "ExceptionCode.h"
+#include "JSDOMBinding.h"
+#include <runtime/CallData.h>
+
+namespace WebCore {
+
+bool checkFunctionOnlyCallback(JSC::ExecState* exec, JSC::JSValue value, CallbackAllowedValueFlags acceptedValues)
+{
+ if (value.isUndefined() && (acceptedValues & CallbackAllowUndefined))
+ return false;
+
+ if (value.isNull() && (acceptedValues & CallbackAllowNull))
+ return false;
+
+ JSC::CallData callData;
+ if (getCallData(value, callData) == JSC::CallTypeNone) {
+ setDOMException(exec, TYPE_MISMATCH_ERR);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/CallbackFunction.h b/Source/WebCore/bindings/js/CallbackFunction.h
new file mode 100644
index 0000000..2562ce9
--- /dev/null
+++ b/Source/WebCore/bindings/js/CallbackFunction.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 CallbackFunction_h
+#define CallbackFunction_h
+
+#include <runtime/JSObject.h>
+
+namespace JSC {
+class ExecState;
+}
+
+namespace WebCore {
+
+class JSDOMGlobalObject;
+
+enum CallbackAllowedValueFlag {
+ CallbackAllowUndefined = 1,
+ CallbackAllowNull = 1 << 1
+};
+
+typedef unsigned CallbackAllowedValueFlags;
+
+bool checkFunctionOnlyCallback(JSC::ExecState*, JSC::JSValue, CallbackAllowedValueFlags);
+
+// Creates callback objects for callbacks marked as FunctionOnly in WebIDL.
+template <typename JSCallbackType>
+PassRefPtr<JSCallbackType> createFunctionOnlyCallback(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::JSValue value, CallbackAllowedValueFlags acceptedValues = 0)
+{
+ if (checkFunctionOnlyCallback(exec, value, acceptedValues))
+ return JSCallbackType::create(asObject(value), globalObject);
+ return 0;
+}
+
+} // namespace WebCore
+
+#endif // CallbackFunction_h
diff --git a/Source/WebCore/bindings/js/DOMWrapperWorld.cpp b/Source/WebCore/bindings/js/DOMWrapperWorld.cpp
index 13ee37a..b78211e 100644
--- a/Source/WebCore/bindings/js/DOMWrapperWorld.cpp
+++ b/Source/WebCore/bindings/js/DOMWrapperWorld.cpp
@@ -29,9 +29,17 @@ using namespace JSC;
namespace WebCore {
+void JSDOMWrapperOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+ JSDOMWrapper* wrapper = static_cast<JSDOMWrapper*>(handle.get().asCell());
+ void* domObject = context;
+ uncacheWrapper(m_world, domObject, wrapper);
+}
+
DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal)
: m_globalData(globalData)
, m_isNormal(isNormal)
+ , m_defaultWrapperOwner(this)
{
JSGlobalData::ClientData* clientData = m_globalData->clientData;
ASSERT(clientData);
@@ -45,9 +53,6 @@ DOMWrapperWorld::~DOMWrapperWorld()
static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this);
// These items are created lazily.
- while (!m_documentsWithWrapperCaches.isEmpty())
- (*m_documentsWithWrapperCaches.begin())->destroyWrapperCache(this);
-
while (!m_scriptControllersWithWindowShells.isEmpty())
(*m_scriptControllersWithWindowShells.begin())->destroyWindowShell(this);
}
@@ -58,9 +63,6 @@ void DOMWrapperWorld::clearWrappers()
m_stringCache.clear();
// These items are created lazily.
- while (!m_documentsWithWrapperCaches.isEmpty())
- (*m_documentsWithWrapperCaches.begin())->destroyWrapperCache(this);
-
while (!m_scriptControllersWithWindowShells.isEmpty())
(*m_scriptControllersWithWindowShells.begin())->destroyWindowShell(this);
}
diff --git a/Source/WebCore/bindings/js/DOMWrapperWorld.h b/Source/WebCore/bindings/js/DOMWrapperWorld.h
index 9825a08..cd7c59f 100644
--- a/Source/WebCore/bindings/js/DOMWrapperWorld.h
+++ b/Source/WebCore/bindings/js/DOMWrapperWorld.h
@@ -22,18 +22,32 @@
#ifndef DOMWrapperWorld_h
#define DOMWrapperWorld_h
-#include "Document.h"
#include "JSDOMGlobalObject.h"
-#include "JSDOMWrapper.h"
+#include <heap/Weak.h>
#include <runtime/WeakGCMap.h>
#include <wtf/Forward.h>
namespace WebCore {
+class JSDOMWrapper;
class ScriptController;
-typedef JSC::WeakGCMap<void*, DOMObject> DOMObjectWrapperMap;
-typedef JSC::WeakGCMap<StringImpl*, JSC::JSString> JSStringCache;
+typedef HashMap<void*, JSC::Weak<JSDOMWrapper> > DOMObjectWrapperMap;
+typedef JSC::WeakGCMap<StringImpl*, JSC::JSString> JSStringCache;
+
+class JSDOMWrapperOwner : public JSC::WeakHandleOwner {
+public:
+ JSDOMWrapperOwner(DOMWrapperWorld*);
+ virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+
+private:
+ DOMWrapperWorld* m_world;
+};
+
+inline JSDOMWrapperOwner::JSDOMWrapperOwner(DOMWrapperWorld* world)
+ : m_world(world)
+{
+}
class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
public:
@@ -46,9 +60,6 @@ public:
// Free as much memory held onto by this world as possible.
void clearWrappers();
- void didCreateWrapperCache(Document* document) { m_documentsWithWrapperCaches.add(document); }
- void didDestroyWrapperCache(Document* document) { m_documentsWithWrapperCaches.remove(document); }
-
void didCreateWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.add(scriptController); }
void didDestroyWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.remove(scriptController); }
@@ -59,15 +70,16 @@ public:
bool isNormal() const { return m_isNormal; }
JSC::JSGlobalData* globalData() const { return m_globalData; }
+ JSDOMWrapperOwner* defaultWrapperOwner() { return &m_defaultWrapperOwner; }
protected:
DOMWrapperWorld(JSC::JSGlobalData*, bool isNormal);
private:
JSC::JSGlobalData* m_globalData;
- HashSet<Document*> m_documentsWithWrapperCaches;
HashSet<ScriptController*> m_scriptControllersWithWindowShells;
bool m_isNormal;
+ JSDOMWrapperOwner m_defaultWrapperOwner;
};
DOMWrapperWorld* normalWorld(JSC::JSGlobalData&);
@@ -80,19 +92,6 @@ inline DOMWrapperWorld* currentWorld(JSC::ExecState* exec)
return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world();
}
-// From Document.h
-
-inline Document::JSWrapperCache* Document::getWrapperCache(DOMWrapperWorld* world)
-{
- if (world->isNormal()) {
- if (Document::JSWrapperCache* wrapperCache = m_normalWorldWrapperCache)
- return wrapperCache;
- ASSERT(!m_wrapperCacheMap.contains(world));
- } else if (Document::JSWrapperCache* wrapperCache = m_wrapperCacheMap.get(world))
- return wrapperCache;
- return createWrapperCache(world);
-}
-
} // namespace WebCore
#endif // DOMWrapperWorld_h
diff --git a/Source/WebCore/bindings/js/GCController.cpp b/Source/WebCore/bindings/js/GCController.cpp
index fe0e36f..765e363 100644
--- a/Source/WebCore/bindings/js/GCController.cpp
+++ b/Source/WebCore/bindings/js/GCController.cpp
@@ -29,13 +29,9 @@
#include "JSDOMWindow.h"
#include <runtime/JSGlobalData.h>
#include <runtime/JSLock.h>
-#include <runtime/Heap.h>
+#include <heap/Heap.h>
#include <wtf/StdLibExtras.h>
-#if USE(PTHREADS)
-#include <pthread.h>
-#endif
-
using namespace JSC;
namespace WebCore {
@@ -78,13 +74,14 @@ void GCController::garbageCollectNow()
void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone)
{
-#if USE(PTHREADS)
- pthread_t thread;
- pthread_create(&thread, NULL, collect, NULL);
+ ThreadIdentifier threadID = createThread(collect, 0, "WebCore: GCController");
+
+ if (waitUntilDone) {
+ waitForThreadCompletion(threadID, 0);
+ return;
+ }
- if (waitUntilDone)
- pthread_join(thread, NULL);
-#endif
+ detachThread(threadID);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSArrayBufferViewHelper.h b/Source/WebCore/bindings/js/JSArrayBufferViewHelper.h
index cb9981d..58aaf19 100644
--- a/Source/WebCore/bindings/js/JSArrayBufferViewHelper.h
+++ b/Source/WebCore/bindings/js/JSArrayBufferViewHelper.h
@@ -163,11 +163,11 @@ static JSC::JSValue toJSArrayBufferView(JSC::ExecState* exec, JSDOMGlobalObject*
if (!object)
return JSC::jsNull();
- if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object))
+ if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), object))
return wrapper;
exec->heap()->reportExtraMemoryCost(object->byteLength());
- return createDOMObjectWrapper<JSType>(exec, globalObject, object);
+ return createWrapper<JSType>(exec, globalObject, object);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSAttrCustom.cpp b/Source/WebCore/bindings/js/JSAttrCustom.cpp
index 227582d..305dc81 100644
--- a/Source/WebCore/bindings/js/JSAttrCustom.cpp
+++ b/Source/WebCore/bindings/js/JSAttrCustom.cpp
@@ -43,10 +43,10 @@ void JSAttr::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
- // Mark the element so that this will work to access the attribute even if the last
- // other reference goes away.
- if (Element* element = impl()->ownerElement())
- markDOMNodeWrapper(markStack, element->document(), element);
+ Element* element = impl()->ownerElement();
+ if (!element)
+ return;
+ markStack.addOpaqueRoot(root(element));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSAudioConstructor.h b/Source/WebCore/bindings/js/JSAudioConstructor.h
index be0b800..1440355 100644
--- a/Source/WebCore/bindings/js/JSAudioConstructor.h
+++ b/Source/WebCore/bindings/js/JSAudioConstructor.h
@@ -38,7 +38,7 @@ namespace WebCore {
public:
JSAudioConstructor(JSC::ExecState*, JSDOMGlobalObject*);
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
diff --git a/Source/WebCore/bindings/js/JSAudioContextCustom.cpp b/Source/WebCore/bindings/js/JSAudioContextCustom.cpp
index 382d0cb..9ebf6b7 100644
--- a/Source/WebCore/bindings/js/JSAudioContextCustom.cpp
+++ b/Source/WebCore/bindings/js/JSAudioContextCustom.cpp
@@ -54,8 +54,28 @@ EncodedJSValue JSC_HOST_CALL JSAudioContextConstructor::constructJSAudioContext(
Document* document = static_cast<Document*>(scriptExecutionContext);
- RefPtr<AudioContext> context = AudioContext::create(document);
- return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), context.get())));
+ RefPtr<AudioContext> audioContext;
+
+ if (!exec->argumentCount()) {
+ // Constructor for default AudioContext which talks to audio hardware.
+ audioContext = AudioContext::create(document);
+ } else {
+ // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer.
+ // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
+ if (exec->argumentCount() < 3)
+ return throwError(exec, createSyntaxError(exec, "Not enough arguments"));
+
+ unsigned numberOfChannels = exec->argument(0).toInt32(exec);
+ unsigned numberOfFrames = exec->argument(1).toInt32(exec);
+ float sampleRate = exec->argument(2).toFloat(exec);
+
+ audioContext = AudioContext::createOfflineContext(document, numberOfChannels, numberOfFrames, sampleRate);
+ }
+
+ if (!audioContext.get())
+ return throwError(exec, createReferenceError(exec, "Error creating AudioContext"));
+
+ return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), audioContext.get())));
}
JSValue JSAudioContext::createBuffer(ExecState* exec)
diff --git a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
index d5c9135..a457ce8 100644
--- a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
+++ b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
@@ -25,6 +25,7 @@
// This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build.
+#include "CallbackFunction.cpp"
#include "DOMObjectHashTableMap.cpp"
#include "DOMWrapperWorld.cpp"
#include "GCController.cpp"
diff --git a/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp b/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
index 4d226d0..935ec1a 100644
--- a/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
@@ -63,7 +63,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSRule* rule)
if (!rule)
return jsNull();
- DOMObject* wrapper = getCachedDOMObjectWrapper(exec, rule);
+ JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), rule);
if (wrapper)
return wrapper;
diff --git a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
index 1e750e5..c41c15b 100644
--- a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
@@ -34,6 +34,8 @@
#include <runtime/StringPrototype.h>
#include <wtf/ASCIICType.h>
#include <wtf/text/AtomicString.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringConcatenate.h>
using namespace JSC;
using namespace WTF;
@@ -94,8 +96,8 @@ static String cssPropertyName(const Identifier& propertyName, bool* hadPixelOrPo
if (!length)
return String();
- Vector<UChar> name;
- name.reserveInitialCapacity(length);
+ StringBuilder builder;
+ builder.reserveCapacity(length);
unsigned i = 0;
@@ -112,32 +114,30 @@ static String cssPropertyName(const Identifier& propertyName, bool* hadPixelOrPo
} else if (hasCSSPropertyNamePrefix(propertyName, "webkit")
|| hasCSSPropertyNamePrefix(propertyName, "khtml")
|| hasCSSPropertyNamePrefix(propertyName, "apple"))
- name.append('-');
+ builder.append('-');
else {
if (isASCIIUpper(propertyName.characters()[0]))
return String();
}
- name.append(toASCIILower(propertyName.characters()[i++]));
+ builder.append(toASCIILower(propertyName.characters()[i++]));
for (; i < length; ++i) {
UChar c = propertyName.characters()[i];
if (!isASCIIUpper(c))
- name.append(c);
- else {
- name.append('-');
- name.append(toASCIILower(c));
- }
+ builder.append(c);
+ else
+ builder.append(makeString('-', toASCIILower(c)));
}
- return String::adopt(name);
+ return builder.toString();
}
-static bool isCSSPropertyName(const Identifier& propertyName)
+static bool isCSSPropertyName(const Identifier& propertyIdentifier)
{
// FIXME: This mallocs a string for the property name and then throws it
// away. This shows up on peacekeeper's domDynamicCreationCreateElement.
- return CSSStyleDeclaration::isPropertyName(cssPropertyName(propertyName));
+ return CSSStyleDeclaration::isPropertyName(cssPropertyName(propertyIdentifier));
}
bool JSCSSStyleDeclaration::canGetItemsForName(ExecState*, CSSStyleDeclaration*, const Identifier& propertyName)
@@ -178,11 +178,11 @@ JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, JSValue slotBase, con
bool JSCSSStyleDeclaration::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&)
{
- if (!isCSSPropertyName(propertyName))
- return false;
-
bool pixelOrPos;
String prop = cssPropertyName(propertyName, &pixelOrPos);
+ if (!CSSStyleDeclaration::isPropertyName(prop))
+ return false;
+
String propValue = valueToStringWithNullCheck(exec, value);
if (pixelOrPos)
propValue += "px";
diff --git a/Source/WebCore/bindings/js/JSCSSValueCustom.cpp b/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
index 83c1d3a..b1f8404 100644
--- a/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
@@ -49,7 +49,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSValue* value)
if (!value)
return jsNull();
- DOMObject* wrapper = getCachedDOMObjectWrapper(exec, value);
+ JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), value);
if (wrapper)
return wrapper;
diff --git a/Source/WebCore/bindings/js/JSCallbackData.h b/Source/WebCore/bindings/js/JSCallbackData.h
index 942cd9c..94ca48d 100644
--- a/Source/WebCore/bindings/js/JSCallbackData.h
+++ b/Source/WebCore/bindings/js/JSCallbackData.h
@@ -32,7 +32,7 @@
#include "JSDOMBinding.h"
#include "JSDOMGlobalObject.h"
#include "ScriptExecutionContext.h"
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <runtime/JSObject.h>
#include <wtf/Threading.h>
@@ -66,8 +66,8 @@ public:
JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer&, bool* raisedException = 0);
private:
- JSC::Global<JSC::JSObject> m_callback;
- JSC::Global<JSDOMGlobalObject> m_globalObject;
+ JSC::Strong<JSC::JSObject> m_callback;
+ JSC::Strong<JSDOMGlobalObject> m_globalObject;
#ifndef NDEBUG
ThreadIdentifier m_thread;
#endif
diff --git a/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp b/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp
index cab7ba3..cd20dc9 100644
--- a/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp
@@ -44,10 +44,10 @@ JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasR
#if ENABLE(WEBGL)
if (object->is3d())
- return getDOMObjectWrapper<JSWebGLRenderingContext>(exec, globalObject, static_cast<WebGLRenderingContext*>(object));
+ return wrap<JSWebGLRenderingContext>(exec, globalObject, static_cast<WebGLRenderingContext*>(object));
#endif
ASSERT(object->is2d());
- return getDOMObjectWrapper<JSCanvasRenderingContext2D>(exec, globalObject, static_cast<CanvasRenderingContext2D*>(object));
+ return wrap<JSCanvasRenderingContext2D>(exec, globalObject, static_cast<CanvasRenderingContext2D*>(object));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCustomVoidCallback.h b/Source/WebCore/bindings/js/JSCustomVoidCallback.h
index 922e380..f342b8b 100644
--- a/Source/WebCore/bindings/js/JSCustomVoidCallback.h
+++ b/Source/WebCore/bindings/js/JSCustomVoidCallback.h
@@ -31,7 +31,7 @@
#include "JSDOMGlobalObject.h"
#include "VoidCallback.h"
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <wtf/Forward.h>
namespace WebCore {
diff --git a/Source/WebCore/bindings/js/JSDOMBinding.cpp b/Source/WebCore/bindings/js/JSDOMBinding.cpp
index 8501eb9..5ac07a7 100644
--- a/Source/WebCore/bindings/js/JSDOMBinding.cpp
+++ b/Source/WebCore/bindings/js/JSDOMBinding.cpp
@@ -44,7 +44,6 @@
#include "JSEventException.h"
#include "JSExceptionBase.h"
#include "JSMainThreadExecState.h"
-#include "JSNode.h"
#include "JSRangeException.h"
#include "JSXMLHttpRequestException.h"
#include "KURL.h"
@@ -94,9 +93,6 @@ namespace WebCore {
using namespace HTMLNames;
-typedef Document::JSWrapperCache JSWrapperCache;
-typedef Document::JSWrapperCacheMap JSWrapperCacheMap;
-
class JSGlobalDataWorldIterator {
public:
JSGlobalDataWorldIterator(JSGlobalData* globalData)
@@ -138,163 +134,6 @@ const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const
return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);
}
-bool hasCachedDOMObjectWrapperUnchecked(JSGlobalData* globalData, void* objectHandle)
-{
- for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
- if (worldIter->m_wrappers.get(objectHandle))
- return true;
- }
- return false;
-}
-
-bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle)
-{
- for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
- if (worldIter->m_wrappers.get(objectHandle))
- return true;
- }
- return false;
-}
-
-DOMObject* getCachedDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle)
-{
- return domObjectWrapperMapFor(exec).get(objectHandle);
-}
-
-void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject* wrapper)
-{
- domObjectWrapperMapFor(exec).set(exec->globalData(), objectHandle, wrapper);
-}
-
-bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node)
-{
- if (!document)
- return hasCachedDOMObjectWrapperUnchecked(JSDOMWindow::commonJSGlobalData(), node);
-
- JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
- for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
- if (iter->second->get(node))
- return true;
- }
- return false;
-}
-
-void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper)
-{
- if (!document)
- domObjectWrapperMapFor(exec).set(exec->globalData(), node, wrapper);
- else
- document->getWrapperCache(currentWorld(exec))->set(exec->globalData(), node, wrapper);
-
- if (currentWorld(exec)->isNormal())
- node->setWrapper(exec->globalData(), wrapper);
-}
-
-static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world)
-{
- // Certain conditions implicitly make existence of a JS DOM node wrapper observable
- // through the DOM, even if no explicit reference to it remains.
-
- Node* node = jsNode->impl();
-
- if (node->inDocument()) {
- // If a node is in the document, and its wrapper has custom properties,
- // the wrapper is observable because future access to the node through the
- // DOM must reflect those properties.
- if (jsNode->hasCustomProperties())
- return true;
-
- // If a node is in the document, and has event listeners, its wrapper is
- // observable because its wrapper is responsible for marking those event listeners.
- if (node->hasEventListeners())
- return true; // Technically, we may overzealously mark a wrapper for a node that has only non-JS event listeners. Oh well.
-
- // If a node owns another object with a wrapper with custom properties,
- // the wrapper must be treated as observable, because future access to
- // those objects through the DOM must reflect those properties.
- // FIXME: It would be better if this logic could be in the node next to
- // the custom markChildren functions rather than here.
- // Note that for some compound objects like stylesheets and CSSStyleDeclarations,
- // we don't descend to check children for custom properties, and just conservatively
- // keep the node wrappers protecting them alive.
- if (node->isElementNode()) {
- if (NamedNodeMap* attributes = static_cast<Element*>(node)->attributeMap()) {
- if (DOMObject* wrapper = world->m_wrappers.get(attributes)) {
- // FIXME: This check seems insufficient, because NamedNodeMap items can have custom properties themselves.
- // Maybe it would be OK to just keep the wrapper alive, as it is done for CSSOM objects below.
- if (wrapper->hasCustomProperties())
- return true;
- }
- }
- if (node->isStyledElement()) {
- if (CSSMutableStyleDeclaration* style = static_cast<StyledElement*>(node)->inlineStyleDecl()) {
- if (world->m_wrappers.get(style))
- return true;
- }
- }
- if (static_cast<Element*>(node)->hasTagName(canvasTag)) {
- if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) {
- if (DOMObject* wrapper = world->m_wrappers.get(context)) {
- if (wrapper->hasCustomProperties())
- return true;
- }
- }
- } else if (static_cast<Element*>(node)->hasTagName(linkTag)) {
- if (StyleSheet* sheet = static_cast<HTMLLinkElement*>(node)->sheet()) {
- if (world->m_wrappers.get(sheet))
- return true;
- }
- } else if (static_cast<Element*>(node)->hasTagName(styleTag)) {
- if (StyleSheet* sheet = static_cast<HTMLStyleElement*>(node)->sheet()) {
- if (world->m_wrappers.get(sheet))
- return true;
- }
- }
- } else if (node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
- if (StyleSheet* sheet = static_cast<ProcessingInstruction*>(node)->sheet()) {
- if (world->m_wrappers.get(sheet))
- return true;
- }
- }
- } else {
- // If a wrapper is the last reference to an image or script element
- // that is loading but not in the document, the wrapper is observable
- // because it is the only thing keeping the image element alive, and if
- // the image element is destroyed, its load event will not fire.
- // FIXME: The DOM should manage this issue without the help of JavaScript wrappers.
- if (node->hasTagName(imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())
- return true;
- if (node->hasTagName(scriptTag) && !static_cast<HTMLScriptElement*>(node)->haveFiredLoadEvent())
- return true;
-#if ENABLE(VIDEO)
- if (node->hasTagName(audioTag) && !static_cast<HTMLAudioElement*>(node)->paused())
- return true;
-#endif
- }
-
- // If a node is firing event listeners, its wrapper is observable because
- // its wrapper is responsible for marking those event listeners.
- if (node->isFiringEventListeners())
- return true;
-
- return false;
-}
-
-void markDOMNodesForDocument(MarkStack& markStack, Document* document)
-{
- JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
- for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) {
- DOMWrapperWorld* world = wrappersIter->first;
- JSWrapperCache* nodeDict = wrappersIter->second;
-
- JSWrapperCache::iterator nodeEnd = nodeDict->end();
- for (JSWrapperCache::iterator nodeIt = nodeDict->begin(); nodeIt != nodeEnd; ++nodeIt) {
- if (isObservableThroughDOM(nodeIt.get().second, world))
- markStack.deprecatedAppend(nodeIt.getSlot().second);
- }
- }
-}
-
void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, ScriptExecutionContext* scriptExecutionContext)
{
// If an element has pending activity that may result in event listeners being called
@@ -319,42 +158,6 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData,
}
}
-typedef std::pair<JSNode*, DOMWrapperWorld*> WrapperAndWorld;
-typedef WTF::Vector<WrapperAndWorld, 8> WrapperSet;
-
-static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrapperSet)
-{
- if (document) {
- JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
- for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
- if (JSNode* wrapper = iter->second->take(node))
- wrapperSet.append(WrapperAndWorld(wrapper, iter->first));
- }
- } else {
- for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) {
- DOMWrapperWorld* world = *worldIter;
- if (JSNode* wrapper = static_cast<JSNode*>(world->m_wrappers.take(node)))
- wrapperSet.append(WrapperAndWorld(wrapper, world));
- }
- }
-}
-
-void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocument)
-{
- ASSERT(oldDocument != newDocument);
-
- WrapperSet wrapperSet;
- takeWrappers(node, oldDocument, wrapperSet);
-
- for (unsigned i = 0; i < wrapperSet.size(); ++i) {
- JSNode* wrapper = wrapperSet[i].first;
- if (newDocument)
- newDocument->getWrapperCache(wrapperSet[i].second)->set(*wrapperSet[i].second->globalData(), node, wrapper);
- else
- wrapperSet[i].second->m_wrappers.set(*wrapperSet[i].second->globalData(), node, wrapper);
- }
-}
-
void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* object)
{
// FIXME: This could be changed to only mark wrappers that are "observable"
@@ -364,25 +167,8 @@ void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void*
return;
for (JSGlobalDataWorldIterator worldIter(&globalData); worldIter; ++worldIter) {
- if (HandleSlot wrapperSlot = worldIter->m_wrappers.getSlot(object))
- markStack.deprecatedAppend(wrapperSlot);
- }
-}
-
-void markDOMNodeWrapper(MarkStack& markStack, Document* document, Node* node)
-{
- if (document) {
- JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
- for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
- if (HandleSlot wrapperSlot = iter->second->getSlot(node))
- markStack.deprecatedAppend(wrapperSlot);
- }
- return;
- }
-
- for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) {
- if (HandleSlot wrapperSlot = worldIter->m_wrappers.getSlot(node))
- markStack.deprecatedAppend(wrapperSlot);
+ if (JSDOMWrapper* wrapper = worldIter->m_wrappers.get(object).get())
+ markStack.deprecatedAppend(reinterpret_cast<JSCell**>(&wrapper));
}
}
@@ -646,11 +432,11 @@ Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInf
return structures.get(classInfo).get();
}
-Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const ClassInfo* classInfo)
+Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, Structure* structure, const ClassInfo* classInfo)
{
JSDOMStructureMap& structures = globalObject->structures();
ASSERT(!structures.contains(classInfo));
- return structures.set(classInfo, structure).first->second.get();
+ return structures.set(classInfo, WriteBarrier<Structure>(globalObject->globalData(), globalObject, structure)).first->second.get();
}
JSC::JSObject* toJSSequence(ExecState* exec, JSValue value, unsigned& length)
diff --git a/Source/WebCore/bindings/js/JSDOMBinding.h b/Source/WebCore/bindings/js/JSDOMBinding.h
index 934d9b3..803429f 100644
--- a/Source/WebCore/bindings/js/JSDOMBinding.h
+++ b/Source/WebCore/bindings/js/JSDOMBinding.h
@@ -26,9 +26,9 @@
#include "JSDOMWrapper.h"
#include "DOMWrapperWorld.h"
#include "Document.h"
+#include <heap/Weak.h>
#include <runtime/Completion.h>
#include <runtime/Lookup.h>
-#include <runtime/WeakGCMap.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
@@ -49,13 +49,13 @@ namespace WebCore {
typedef int ExceptionCode;
- // FIXME: This class should collapse into DOMObject once all DOMObjects are
+ // FIXME: This class should collapse into JSDOMWrapper once all JSDOMWrappers are
// updated to store a globalObject pointer.
- class DOMObjectWithGlobalPointer : public DOMObject {
+ class JSDOMWrapperWithGlobalPointer : public JSDOMWrapper {
public:
JSDOMGlobalObject* globalObject() const
{
- return static_cast<JSDOMGlobalObject*>(DOMObject::globalObject());
+ return static_cast<JSDOMGlobalObject*>(JSDOMWrapper::globalObject());
}
ScriptExecutionContext* scriptExecutionContext() const
@@ -64,14 +64,14 @@ namespace WebCore {
return globalObject()->scriptExecutionContext();
}
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
- DOMObjectWithGlobalPointer(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
- : DOMObject(globalObject, structure)
+ JSDOMWrapperWithGlobalPointer(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
+ : JSDOMWrapper(globalObject, structure)
{
// FIXME: This ASSERT is valid, but fires in fast/dom/gc-6.html when trying to create
// new JavaScript objects on detached windows due to DOMWindow::document()
@@ -81,17 +81,17 @@ namespace WebCore {
};
// Base class for all constructor objects in the JSC bindings.
- class DOMConstructorObject : public DOMObjectWithGlobalPointer {
+ class DOMConstructorObject : public JSDOMWrapperWithGlobalPointer {
public:
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
protected:
- static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesMarkChildren | DOMObjectWithGlobalPointer::StructureFlags;
- DOMConstructorObject(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
- : DOMObjectWithGlobalPointer(structure, globalObject)
+ static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesMarkChildren | JSDOMWrapperWithGlobalPointer::StructureFlags;
+ DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
+ : JSDOMWrapperWithGlobalPointer(structure, globalObject)
{
}
};
@@ -106,30 +106,18 @@ namespace WebCore {
}
protected:
- DOMConstructorWithDocument(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
+ DOMConstructorWithDocument(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
: DOMConstructorObject(structure, globalObject)
{
ASSERT(globalObject->scriptExecutionContext()->isDocument());
}
};
-
- DOMObject* getCachedDOMObjectWrapper(JSC::ExecState*, void* objectHandle);
- bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle);
- void cacheDOMObjectWrapper(JSC::ExecState*, void* objectHandle, DOMObject* wrapper);
-
- JSNode* getCachedDOMNodeWrapper(JSC::ExecState*, Document*, Node*);
- void cacheDOMNodeWrapper(JSC::ExecState*, Document*, Node*, JSNode* wrapper);
- void updateDOMNodeDocument(Node*, Document* oldDocument, Document* newDocument);
-
- void markDOMNodesForDocument(JSC::MarkStack&, Document*);
+
void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*);
void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object);
- void markDOMNodeWrapper(JSC::MarkStack& markStack, Document* document, Node* node);
- bool hasCachedDOMObjectWrapperUnchecked(JSC::JSGlobalData*, void* objectHandle);
- bool hasCachedDOMNodeWrapperUnchecked(Document*, Node*);
JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*);
- JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
+ JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, JSC::Structure*, const JSC::ClassInfo*);
inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec)
{
@@ -145,52 +133,70 @@ namespace WebCore {
return structure;
return cacheDOMStructure(globalObject, WrapperClass::createStructure(exec->globalData(), WrapperClass::createPrototype(exec, globalObject)), &WrapperClass::s_info);
}
+
template<class WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec)
{
// FIXME: This function is wrong. It uses the wrong global object for creating the prototype structure.
return getDOMStructure<WrapperClass>(exec, deprecatedGlobalObjectForPrototype(exec));
}
+
template<class WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject)
{
return static_cast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(exec, static_cast<JSDOMGlobalObject*>(globalObject))->storedPrototype()));
}
- #define CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, className, object) createDOMObjectWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
- template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object)
+
+ // Overload these functions to provide a fast path for wrapper access.
+ inline JSDOMWrapper* getInlineCachedWrapper(DOMWrapperWorld*, void*) { return 0; }
+ inline bool setInlineCachedWrapper(DOMWrapperWorld*, void*, JSDOMWrapper*) { return false; }
+ inline bool clearInlineCachedWrapper(DOMWrapperWorld*, void*, JSDOMWrapper*) { return false; }
+
+ // Overload these functions to provide a custom WeakHandleOwner.
+ inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld* world, void*) { return world->defaultWrapperOwner(); }
+ inline void* wrapperContext(DOMWrapperWorld*, void* domObject) { return domObject; }
+
+ template <typename DOMClass> inline JSDOMWrapper* getCachedWrapper(DOMWrapperWorld* world, DOMClass* domObject)
{
- ASSERT(object);
- ASSERT(!getCachedDOMObjectWrapper(exec, object));
- // FIXME: new (exec) could use a different globalData than the globalData this wrapper is cached on.
- WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object);
- cacheDOMObjectWrapper(exec, object, wrapper);
- return wrapper;
+ if (JSDOMWrapper* wrapper = getInlineCachedWrapper(world, domObject))
+ return wrapper;
+ return world->m_wrappers.get(domObject).get();
}
- template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object)
+
+ template <typename DOMClass> inline void cacheWrapper(DOMWrapperWorld* world, DOMClass* domObject, JSDOMWrapper* wrapper)
{
- if (!object)
- return JSC::jsNull();
- if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object))
- return wrapper;
- return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object);
+ if (setInlineCachedWrapper(world, domObject, wrapper))
+ return;
+ ASSERT(!world->m_wrappers.contains(domObject));
+ world->m_wrappers.set(domObject, JSC::Weak<JSDOMWrapper>(*world->globalData(), wrapper, wrapperOwner(world, domObject), wrapperContext(world, domObject)));
}
- #define CREATE_DOM_NODE_WRAPPER(exec, globalObject, className, object) createDOMNodeWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
- template<class WrapperClass, class DOMClass> inline JSNode* createDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
+ template <typename DOMClass> inline void uncacheWrapper(DOMWrapperWorld* world, DOMClass* domObject, JSDOMWrapper* wrapper)
+ {
+ if (clearInlineCachedWrapper(world, domObject, wrapper))
+ return;
+ ASSERT(world->m_wrappers.find(domObject)->second.get() == wrapper);
+ world->m_wrappers.remove(domObject);
+ }
+
+ #define CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, className, object) createWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
+ #define CREATE_DOM_NODE_WRAPPER(exec, globalObject, className, object) static_cast<JSNode*>(createWrapper<JS##className>(exec, globalObject, static_cast<className*>(object)))
+ template<class WrapperClass, class DOMClass> inline JSDOMWrapper* createWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
{
ASSERT(node);
- ASSERT(!getCachedDOMNodeWrapper(exec, node->document(), node));
+ ASSERT(!getCachedWrapper(currentWorld(exec), node));
WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, node);
// FIXME: The entire function can be removed, once we fix caching.
// This function is a one-off hack to make Nodes cache in the right global object.
- cacheDOMNodeWrapper(exec, node->document(), node, wrapper);
+ cacheWrapper(currentWorld(exec), node, wrapper);
return wrapper;
}
- template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
+
+ template<class WrapperClass, class DOMClass> inline JSC::JSValue wrap(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* domObject)
{
- if (!node)
+ if (!domObject)
return JSC::jsNull();
- if (JSC::JSCell* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node))
+ if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), domObject))
return wrapper;
- return createDOMNodeWrapper<WrapperClass>(exec, globalObject, node);
+ return createWrapper<WrapperClass>(exec, globalObject, domObject);
}
const JSC::HashTable* getHashTableForGlobalData(JSC::JSGlobalData&, const JSC::HashTable* staticTable);
diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp b/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
index 8183b6e..3e3d037 100644
--- a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
+++ b/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
@@ -42,8 +42,8 @@ namespace WebCore {
const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", &JSGlobalObject::s_info, 0, 0 };
-JSDOMGlobalObject::JSDOMGlobalObject(NonNullPassRefPtr<Structure> structure, PassRefPtr<DOMWrapperWorld> world, JSObject* thisValue)
- : JSGlobalObject(structure, thisValue)
+JSDOMGlobalObject::JSDOMGlobalObject(JSGlobalData& globalData, Structure* structure, PassRefPtr<DOMWrapperWorld> world, JSObject* thisValue)
+ : JSGlobalObject(globalData, structure, thisValue)
, m_currentEvent(0)
, m_world(world)
{
@@ -56,7 +56,7 @@ void JSDOMGlobalObject::markChildren(MarkStack& markStack)
JSDOMStructureMap::iterator end = structures().end();
for (JSDOMStructureMap::iterator it = structures().begin(); it != end; ++it)
- markStack.append(it->second->storedPrototypeSlot());
+ markStack.append(&it->second);
JSDOMConstructorMap::iterator end2 = constructors().end();
for (JSDOMConstructorMap::iterator it2 = constructors().begin(); it2 != end2; ++it2)
diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObject.h b/Source/WebCore/bindings/js/JSDOMGlobalObject.h
index 1e992c5..9190e01 100644
--- a/Source/WebCore/bindings/js/JSDOMGlobalObject.h
+++ b/Source/WebCore/bindings/js/JSDOMGlobalObject.h
@@ -38,7 +38,7 @@ namespace WebCore {
class JSEventListener;
class ScriptExecutionContext;
- typedef HashMap<const JSC::ClassInfo*, RefPtr<JSC::Structure> > JSDOMStructureMap;
+ typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::Structure> > JSDOMStructureMap;
typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::JSObject> > JSDOMConstructorMap;
class JSDOMGlobalObject : public JSC::JSGlobalObject {
@@ -46,7 +46,7 @@ namespace WebCore {
protected:
struct JSDOMGlobalObjectData;
- JSDOMGlobalObject(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<DOMWrapperWorld>, JSC::JSObject* thisValue);
+ JSDOMGlobalObject(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<DOMWrapperWorld>, JSC::JSObject* thisValue);
public:
JSDOMStructureMap& structures() { return m_structures; }
@@ -69,7 +69,7 @@ namespace WebCore {
static const JSC::ClassInfo s_info;
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
diff --git a/Source/WebCore/bindings/js/JSDOMImplementationCustom.cpp b/Source/WebCore/bindings/js/JSDOMImplementationCustom.cpp
index ac83c69..aa3a607 100644
--- a/Source/WebCore/bindings/js/JSDOMImplementationCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDOMImplementationCustom.cpp
@@ -33,10 +33,10 @@ void JSDOMImplementation::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
- DOMImplementation* domImplementation = impl();
- Document* ownerDocument = domImplementation->ownerDocument();
- if (ownerDocument)
- markDOMNodeWrapper(markStack, ownerDocument, ownerDocument);
+ Document* ownerDocument = impl()->ownerDocument();
+ if (!ownerDocument)
+ return;
+ markStack.addOpaqueRoot(ownerDocument);
}
}
diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
index 584f610..10f7cd9 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
@@ -45,8 +45,8 @@ namespace WebCore {
const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0 };
-JSDOMWindowBase::JSDOMWindowBase(NonNullPassRefPtr<Structure> structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
- : JSDOMGlobalObject(structure, shell->world(), shell)
+JSDOMWindowBase::JSDOMWindowBase(JSGlobalData& globalData, Structure* structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
+ : JSDOMGlobalObject(globalData, structure, shell->world(), shell)
, m_impl(window)
, m_shell(shell)
{
diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.h b/Source/WebCore/bindings/js/JSDOMWindowBase.h
index bfec31c..946f95c 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowBase.h
+++ b/Source/WebCore/bindings/js/JSDOMWindowBase.h
@@ -22,7 +22,7 @@
#include "PlatformString.h"
#include "JSDOMBinding.h"
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/OwnPtr.h>
@@ -44,7 +44,7 @@ namespace WebCore {
class JSDOMWindowBase : public JSDOMGlobalObject {
typedef JSDOMGlobalObject Base;
protected:
- JSDOMWindowBase(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<DOMWindow>, JSDOMWindowShell*);
+ JSDOMWindowBase(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<DOMWindow>, JSDOMWindowShell*);
public:
void updateDocument();
@@ -57,7 +57,7 @@ namespace WebCore {
static const JSC::ClassInfo s_info;
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
index 03f9d68..4bde9e5 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
@@ -441,24 +441,24 @@ JSValue JSDOMWindow::lookupSetter(ExecState* exec, const Identifier& propertyNam
JSValue JSDOMWindow::history(ExecState* exec) const
{
History* history = impl()->history();
- if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, history))
+ if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), history))
return wrapper;
JSDOMWindow* window = const_cast<JSDOMWindow*>(this);
JSHistory* jsHistory = new (exec) JSHistory(getDOMStructure<JSHistory>(exec, window), window, history);
- cacheDOMObjectWrapper(exec, history, jsHistory);
+ cacheWrapper(currentWorld(exec), history, jsHistory);
return jsHistory;
}
JSValue JSDOMWindow::location(ExecState* exec) const
{
Location* location = impl()->location();
- if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, location))
+ if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), location))
return wrapper;
JSDOMWindow* window = const_cast<JSDOMWindow*>(this);
JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, window), window, location);
- cacheDOMObjectWrapper(exec, location, jsLocation);
+ cacheWrapper(currentWorld(exec), location, jsLocation);
return jsLocation;
}
@@ -732,9 +732,14 @@ JSValue JSDOMWindow::postMessage(ExecState* exec)
JSValue JSDOMWindow::setTimeout(ExecState* exec)
{
- OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec));
+ ContentSecurityPolicy* contentSecurityPolicy = impl()->document() ? impl()->document()->contentSecurityPolicy() : 0;
+ OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy);
if (exec->hadException())
return jsUndefined();
+
+ if (!action)
+ return jsNumber(0);
+
int delay = exec->argument(1).toInt32(exec);
ExceptionCode ec = 0;
@@ -746,11 +751,15 @@ JSValue JSDOMWindow::setTimeout(ExecState* exec)
JSValue JSDOMWindow::setInterval(ExecState* exec)
{
- OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec));
+ ContentSecurityPolicy* contentSecurityPolicy = impl()->document() ? impl()->document()->contentSecurityPolicy() : 0;
+ OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy);
if (exec->hadException())
return jsUndefined();
int delay = exec->argument(1).toInt32(exec);
+ if (!action)
+ return jsNumber(0);
+
ExceptionCode ec = 0;
int result = impl()->setInterval(action.release(), delay, ec);
setDOMException(exec, ec);
diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.cpp b/Source/WebCore/bindings/js/JSDOMWindowShell.cpp
index 817e9c0..0aec968 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowShell.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWindowShell.cpp
@@ -44,7 +44,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSDOMWindowShell);
const ClassInfo JSDOMWindowShell::s_info = { "JSDOMWindowShell", &Base::s_info, 0, 0 };
JSDOMWindowShell::JSDOMWindowShell(PassRefPtr<DOMWindow> window, DOMWrapperWorld* world)
- : Base(JSDOMWindowShell::createStructure(*world->globalData(), jsNull()))
+ : Base(*world->globalData(), JSDOMWindowShell::createStructure(*world->globalData(), jsNull()))
, m_world(world)
{
ASSERT(inherits(&s_info));
@@ -60,11 +60,11 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow)
// Explicitly protect the global object's prototype so it isn't collected
// when we allocate the global object. (Once the global object is fully
// constructed, it can mark its own prototype.)
- RefPtr<Structure> prototypeStructure = JSDOMWindowPrototype::createStructure(*JSDOMWindow::commonJSGlobalData(), jsNull());
- Global<JSDOMWindowPrototype> prototype(*JSDOMWindow::commonJSGlobalData(), new JSDOMWindowPrototype(0, prototypeStructure.release()));
+ Structure* prototypeStructure = JSDOMWindowPrototype::createStructure(*JSDOMWindow::commonJSGlobalData(), jsNull());
+ Strong<JSDOMWindowPrototype> prototype(*JSDOMWindow::commonJSGlobalData(), new JSDOMWindowPrototype(*JSDOMWindow::commonJSGlobalData(), 0, prototypeStructure));
- RefPtr<Structure> structure = JSDOMWindow::createStructure(*JSDOMWindow::commonJSGlobalData(), prototype.get());
- JSDOMWindow* jsDOMWindow = new (JSDOMWindow::commonJSGlobalData()) JSDOMWindow(structure.release(), domWindow, this);
+ Structure* structure = JSDOMWindow::createStructure(*JSDOMWindow::commonJSGlobalData(), prototype.get());
+ JSDOMWindow* jsDOMWindow = new (JSDOMWindow::commonJSGlobalData()) JSDOMWindow(*JSDOMWindow::commonJSGlobalData(), structure, domWindow, this);
prototype->putAnonymousValue(*JSDOMWindow::commonJSGlobalData(), 0, jsDOMWindow);
setWindow(*JSDOMWindow::commonJSGlobalData(), jsDOMWindow);
}
diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.h b/Source/WebCore/bindings/js/JSDOMWindowShell.h
index 4307c1c..c2c5336 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowShell.h
+++ b/Source/WebCore/bindings/js/JSDOMWindowShell.h
@@ -48,7 +48,7 @@ namespace WebCore {
{
ASSERT_ARG(window, window);
m_window.set(globalData, this, window);
- setPrototype(window->prototype());
+ setPrototype(globalData, window->prototype());
}
void setWindow(PassRefPtr<DOMWindow>);
@@ -58,7 +58,7 @@ namespace WebCore {
void* operator new(size_t);
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.cpp b/Source/WebCore/bindings/js/JSDOMWrapper.cpp
index c91230b..60c0ed1 100644
--- a/Source/WebCore/bindings/js/JSDOMWrapper.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWrapper.cpp
@@ -34,7 +34,7 @@ namespace WebCore {
#ifndef NDEBUG
-DOMObject::~DOMObject()
+JSDOMWrapper::~JSDOMWrapper()
{
}
diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.h b/Source/WebCore/bindings/js/JSDOMWrapper.h
index 0f8031c..1484dc6 100644
--- a/Source/WebCore/bindings/js/JSDOMWrapper.h
+++ b/Source/WebCore/bindings/js/JSDOMWrapper.h
@@ -26,16 +26,15 @@
namespace WebCore {
-// FIXME: Rename to JSDOMWrapper.
-class DOMObject : public JSC::JSObjectWithGlobalObject {
+class JSDOMWrapper : public JSC::JSObjectWithGlobalObject {
protected:
- explicit DOMObject(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure)
+ explicit JSDOMWrapper(JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
: JSObjectWithGlobalObject(globalObject, structure)
{
}
#ifndef NDEBUG
- virtual ~DOMObject();
+ virtual ~JSDOMWrapper();
#endif
};
diff --git a/Source/WebCore/bindings/js/JSDataGridDataSource.h b/Source/WebCore/bindings/js/JSDataGridDataSource.h
index 684a663..f82ff63 100644
--- a/Source/WebCore/bindings/js/JSDataGridDataSource.h
+++ b/Source/WebCore/bindings/js/JSDataGridDataSource.h
@@ -29,7 +29,7 @@
#if ENABLE(DATAGRID)
#include "DataGridDataSource.h"
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <runtime/JSValue.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
diff --git a/Source/WebCore/bindings/js/JSDataViewCustom.cpp b/Source/WebCore/bindings/js/JSDataViewCustom.cpp
index eaf57bd..48d56d8 100644
--- a/Source/WebCore/bindings/js/JSDataViewCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDataViewCustom.cpp
@@ -44,7 +44,7 @@ enum DataViewAccessType {
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, DataView* object)
{
- return getDOMObjectWrapper<JSDataView>(exec, globalObject, object);
+ return wrap<JSDataView>(exec, globalObject, object);
}
EncodedJSValue JSC_HOST_CALL JSDataViewConstructor::constructJSDataView(ExecState* exec)
diff --git a/Source/WebCore/bindings/js/JSDirectoryEntryCustom.cpp b/Source/WebCore/bindings/js/JSDirectoryEntryCustom.cpp
index ceb3ccb..82d7c1f 100644
--- a/Source/WebCore/bindings/js/JSDirectoryEntryCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDirectoryEntryCustom.cpp
@@ -38,7 +38,7 @@
#include "JSDOMBinding.h"
#include "JSEntryCallback.h"
#include "JSErrorCallback.h"
-#include "JSFlags.h"
+#include "JSWebKitFlags.h"
#include <wtf/Assertions.h>
using namespace JSC;
@@ -58,16 +58,16 @@ JSValue JSDirectoryEntry::getFile(ExecState* exec)
return jsUndefined();
}
- RefPtr<Flags> flags;
- if (!exec->argument(1).isNull() && !exec->argument(1).isUndefined() && exec->argument(1).isObject() && !exec->argument(1).inherits(&JSFlags::s_info)) {
+ RefPtr<WebKitFlags> flags;
+ if (!exec->argument(1).isNull() && !exec->argument(1).isUndefined() && exec->argument(1).isObject() && !exec->argument(1).inherits(&JSWebKitFlags::s_info)) {
JSObject* object = exec->argument(1).getObject();
- flags = Flags::create();
+ flags = WebKitFlags::create();
JSValue jsCreate = object->get(exec, Identifier(exec, "create"));
flags->setCreate(jsCreate.toBoolean(exec));
JSValue jsExclusive = object->get(exec, Identifier(exec, "exclusive"));
flags->setExclusive(jsExclusive.toBoolean(exec));
} else
- flags = toFlags(exec->argument(1));
+ flags = toWebKitFlags(exec->argument(1));
if (exec->hadException())
return jsUndefined();
RefPtr<EntryCallback> successCallback;
@@ -104,16 +104,16 @@ JSValue JSDirectoryEntry::getDirectory(ExecState* exec)
return jsUndefined();
}
- RefPtr<Flags> flags;
- if (!exec->argument(1).isNull() && !exec->argument(1).isUndefined() && exec->argument(1).isObject() && !exec->argument(1).inherits(&JSFlags::s_info)) {
+ RefPtr<WebKitFlags> flags;
+ if (!exec->argument(1).isNull() && !exec->argument(1).isUndefined() && exec->argument(1).isObject() && !exec->argument(1).inherits(&JSWebKitFlags::s_info)) {
JSObject* object = exec->argument(1).getObject();
- flags = Flags::create();
+ flags = WebKitFlags::create();
JSValue jsCreate = object->get(exec, Identifier(exec, "create"));
flags->setCreate(jsCreate.toBoolean(exec));
JSValue jsExclusive = object->get(exec, Identifier(exec, "exclusive"));
flags->setExclusive(jsExclusive.toBoolean(exec));
} else
- flags = toFlags(exec->argument(1));
+ flags = toWebKitFlags(exec->argument(1));
if (exec->hadException())
return jsUndefined();
RefPtr<EntryCallback> successCallback;
diff --git a/Source/WebCore/bindings/js/JSDirectoryEntrySyncCustom.cpp b/Source/WebCore/bindings/js/JSDirectoryEntrySyncCustom.cpp
index ef14b79..21006ab 100644
--- a/Source/WebCore/bindings/js/JSDirectoryEntrySyncCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDirectoryEntrySyncCustom.cpp
@@ -38,23 +38,23 @@
#include "JSEntryCallback.h"
#include "JSErrorCallback.h"
#include "JSFileEntrySync.h"
-#include "JSFlags.h"
+#include "JSWebKitFlags.h"
#include <wtf/Assertions.h>
using namespace JSC;
namespace WebCore {
-static PassRefPtr<Flags> getFlags(ExecState* exec, const JSValue& argument)
+static PassRefPtr<WebKitFlags> getFlags(ExecState* exec, const JSValue& argument)
{
if (argument.isNull() || argument.isUndefined() || !argument.isObject())
return 0;
- if (argument.inherits(&JSFlags::s_info))
+ if (argument.inherits(&JSWebKitFlags::s_info))
return toFlags(argument);
- RefPtr<Flags> flags;
+ RefPtr<WebKitFlags> flags;
JSObject* object = argument.getObject();
- flags = Flags::create();
+ flags = WebKitFlags::create();
JSValue jsCreate = object->get(exec, Identifier(exec, "create"));
flags->setCreate(jsCreate.toBoolean(exec));
JSValue jsExclusive = object->get(exec, Identifier(exec, "exclusive"));
@@ -69,7 +69,7 @@ JSValue JSDirectoryEntrySync::getFile(ExecState* exec)
if (exec->hadException())
return jsUndefined();
- RefPtr<Flags> flags = getFlags(exec, exec->argument(1));
+ RefPtr<WebKitFlags> flags = getFlags(exec, exec->argument(1));
if (exec->hadException())
return jsUndefined();
@@ -86,7 +86,7 @@ JSValue JSDirectoryEntrySync::getDirectory(ExecState* exec)
if (exec->hadException())
return jsUndefined();
- RefPtr<Flags> flags = getFlags(exec, exec->argument(1));
+ RefPtr<WebKitFlags> flags = getFlags(exec, exec->argument(1));
if (exec->hadException())
return jsUndefined();
diff --git a/Source/WebCore/bindings/js/JSDocumentCustom.cpp b/Source/WebCore/bindings/js/JSDocumentCustom.cpp
index fa2b93c..65641cc 100644
--- a/Source/WebCore/bindings/js/JSDocumentCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDocumentCustom.cpp
@@ -55,11 +55,9 @@ void JSDocument::markChildren(MarkStack& markStack)
Document* document = impl();
JSGlobalData& globalData = *Heap::heap(this)->globalData();
- markDOMNodesForDocument(markStack, document);
markActiveObjectsForContext(markStack, globalData, document);
markDOMObjectWrapper(markStack, globalData, document->implementation());
markDOMObjectWrapper(markStack, globalData, document->styleSheets());
- document->markCachedNodeLists(markStack, globalData);
}
JSValue JSDocument::location(ExecState* exec) const
@@ -69,11 +67,11 @@ JSValue JSDocument::location(ExecState* exec) const
return jsNull();
Location* location = frame->domWindow()->location();
- if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, location))
+ if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), location))
return wrapper;
JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, globalObject()), globalObject(), location);
- cacheDOMObjectWrapper(exec, location, jsLocation);
+ cacheWrapper(currentWorld(exec), location, jsLocation);
return jsLocation;
}
@@ -101,7 +99,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* documen
if (!document)
return jsNull();
- DOMObject* wrapper = getCachedDOMNodeWrapper(exec, document, document);
+ JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), document);
if (wrapper)
return wrapper;
diff --git a/Source/WebCore/bindings/js/JSElementCustom.cpp b/Source/WebCore/bindings/js/JSElementCustom.cpp
index 9ed3739..4bedf3a 100644
--- a/Source/WebCore/bindings/js/JSElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSElementCustom.cpp
@@ -71,7 +71,7 @@ JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Eleme
if (!element)
return jsNull();
- ASSERT(!getCachedDOMNodeWrapper(exec, element->document(), element));
+ ASSERT(!getCachedWrapper(currentWorld(exec), element));
JSNode* wrapper;
if (element->isHTMLElement())
diff --git a/Source/WebCore/bindings/js/JSEventCustom.cpp b/Source/WebCore/bindings/js/JSEventCustom.cpp
index 9e95e74..9763b4b 100644
--- a/Source/WebCore/bindings/js/JSEventCustom.cpp
+++ b/Source/WebCore/bindings/js/JSEventCustom.cpp
@@ -101,6 +101,8 @@
#if ENABLE(WEB_AUDIO)
#include "AudioProcessingEvent.h"
#include "JSAudioProcessingEvent.h"
+#include "JSOfflineAudioCompletionEvent.h"
+#include "OfflineAudioCompletionEvent.h"
#endif
using namespace JSC;
@@ -119,7 +121,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event)
if (!event)
return jsNull();
- DOMObject* wrapper = getCachedDOMObjectWrapper(exec, event);
+ JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), event);
if (wrapper)
return wrapper;
@@ -190,6 +192,8 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event)
#if ENABLE(WEB_AUDIO)
else if (event->isAudioProcessingEvent())
wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, AudioProcessingEvent, event);
+ else if (event->isOfflineAudioCompletionEvent())
+ wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, OfflineAudioCompletionEvent, event);
#endif
#if ENABLE(INPUT_SPEECH)
else if (event->isSpeechInputEvent())
diff --git a/Source/WebCore/bindings/js/JSEventListener.cpp b/Source/WebCore/bindings/js/JSEventListener.cpp
index e444d88..436251e 100644
--- a/Source/WebCore/bindings/js/JSEventListener.cpp
+++ b/Source/WebCore/bindings/js/JSEventListener.cpp
@@ -25,6 +25,7 @@
#include "JSEvent.h"
#include "JSEventTarget.h"
#include "JSMainThreadExecState.h"
+#include "WorkerContext.h"
#include <runtime/JSLock.h>
#include <wtf/RefCountedLeakCounter.h>
@@ -38,7 +39,11 @@ JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isA
, m_isAttribute(isAttribute)
, m_isolatedWorld(isolatedWorld)
{
- m_jsFunction.set(*m_isolatedWorld->globalData(), wrapper, function);
+ if (wrapper)
+ m_jsFunction.set(*m_isolatedWorld->globalData(), wrapper, function);
+ else
+ ASSERT(!function);
+
}
JSEventListener::~JSEventListener()
@@ -60,7 +65,7 @@ void JSEventListener::markJSFunction(MarkStack& markStack)
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
ASSERT(scriptExecutionContext);
- if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionTerminated())
+ if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden())
return;
JSLock lock(SilenceAssertionsOnly);
@@ -126,6 +131,14 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext
globalObject->setCurrentEvent(savedEvent);
+#if ENABLE(WORKERS)
+ if (scriptExecutionContext->isWorkerContext()) {
+ bool terminatorCausedException = (exec->hadException() && exec->exception().isObject() && asObject(exec->exception())->exceptionType() == Terminated);
+ if (terminatorCausedException || globalData.terminator.shouldTerminate())
+ static_cast<WorkerContext*>(scriptExecutionContext)->script()->forbidExecution();
+ }
+#endif
+
if (exec->hadException()) {
event->target()->uncaughtExceptionInEventHandler();
reportCurrentException(exec);
diff --git a/Source/WebCore/bindings/js/JSEventListener.h b/Source/WebCore/bindings/js/JSEventListener.h
index 0af0f86..a599be7 100644
--- a/Source/WebCore/bindings/js/JSEventListener.h
+++ b/Source/WebCore/bindings/js/JSEventListener.h
@@ -22,7 +22,7 @@
#include "EventListener.h"
#include "JSDOMWindow.h"
-#include <runtime/WeakGCPtr.h>
+#include <heap/Weak.h>
namespace WebCore {
@@ -66,7 +66,7 @@ namespace WebCore {
private:
mutable JSC::WriteBarrier<JSC::JSObject> m_jsFunction;
- mutable JSC::WeakGCPtr<JSC::JSObject> m_wrapper;
+ mutable JSC::Weak<JSC::JSObject> m_wrapper;
bool m_isAttribute;
RefPtr<DOMWrapperWorld> m_isolatedWorld;
diff --git a/Source/WebCore/bindings/js/JSEventTarget.cpp b/Source/WebCore/bindings/js/JSEventTarget.cpp
index e4d6724..3ccdd6f 100644
--- a/Source/WebCore/bindings/js/JSEventTarget.cpp
+++ b/Source/WebCore/bindings/js/JSEventTarget.cpp
@@ -84,6 +84,8 @@
#endif
#if ENABLE(WEB_AUDIO)
+#include "AudioContext.h"
+#include "JSAudioContext.h"
#include "JSJavaScriptAudioNode.h"
#include "JavaScriptAudioNode.h"
#endif
@@ -173,6 +175,8 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ
#if ENABLE(WEB_AUDIO)
if (JavaScriptAudioNode* jsAudioNode = target->toJavaScriptAudioNode())
return toJS(exec, globalObject, jsAudioNode);
+ if (AudioContext* audioContext = target->toAudioContext())
+ return toJS(exec, globalObject, audioContext);
#endif
#if ENABLE(WEB_SOCKETS)
diff --git a/Source/WebCore/bindings/js/JSGeolocationCustom.cpp b/Source/WebCore/bindings/js/JSGeolocationCustom.cpp
index 248adcf..b93c4ce 100644
--- a/Source/WebCore/bindings/js/JSGeolocationCustom.cpp
+++ b/Source/WebCore/bindings/js/JSGeolocationCustom.cpp
@@ -28,14 +28,13 @@
#if ENABLE(GEOLOCATION)
+#include "CallbackFunction.h"
#include "DOMWindow.h"
-#include "ExceptionCode.h"
#include "Geolocation.h"
#include "JSCustomPositionCallback.h"
#include "JSCustomPositionErrorCallback.h"
#include "JSDOMWindow.h"
#include "PositionOptions.h"
-#include <runtime/JSFunction.h>
#if !ENABLE(CLIENT_BASED_GEOLOCATION)
#include "GeolocationService.h"
@@ -46,36 +45,6 @@ using namespace std;
namespace WebCore {
-static PassRefPtr<PositionCallback> createPositionCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value)
-{
- // The spec specifies 'FunctionOnly' for this object.
- // FIXME: This check disallows callable objects created via JSC API. It's not clear what exactly the specification intends to allow.
- if (!value.inherits(&JSFunction::s_info)) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return 0;
- }
-
- JSObject* object = asObject(value);
- return JSCustomPositionCallback::create(object, globalObject);
-}
-
-static PassRefPtr<PositionErrorCallback> createPositionErrorCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value)
-{
- // Argument is optional (hence undefined is allowed), and null is allowed.
- if (value.isUndefinedOrNull())
- return 0;
-
- // The spec specifies 'FunctionOnly' for this object.
- // FIXME: This check disallows callable objects created via JSC API. It's not clear what exactly the specification intends to allow.
- if (!value.inherits(&JSFunction::s_info)) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return 0;
- }
-
- JSObject* object = asObject(value);
- return JSCustomPositionErrorCallback::create(object, globalObject);
-}
-
static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValue value)
{
// Create default options.
@@ -144,12 +113,12 @@ JSValue JSGeolocation::getCurrentPosition(ExecState* exec)
{
// Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
- RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(0));
+ RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<JSCustomPositionCallback>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(0));
if (exec->hadException())
return jsUndefined();
ASSERT(positionCallback);
- RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(1));
+ RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<JSCustomPositionErrorCallback>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(1), CallbackAllowUndefined | CallbackAllowNull);
if (exec->hadException())
return jsUndefined();
@@ -166,12 +135,12 @@ JSValue JSGeolocation::watchPosition(ExecState* exec)
{
// Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
- RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(0));
+ RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<JSCustomPositionCallback>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(0));
if (exec->hadException())
return jsUndefined();
ASSERT(positionCallback);
- RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(1));
+ RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<JSCustomPositionErrorCallback>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(1), CallbackAllowUndefined | CallbackAllowNull);
if (exec->hadException())
return jsUndefined();
diff --git a/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
index 6b2f350..622a15a 100644
--- a/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
@@ -134,7 +134,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* c
if (!collection)
return jsNull();
- DOMObject* wrapper = getCachedDOMObjectWrapper(exec, collection);
+ JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), collection);
if (wrapper)
return wrapper;
diff --git a/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp b/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
index 192ef5d..c33f859 100644
--- a/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
@@ -86,7 +86,7 @@ JSValue JSHTMLDocument::nameGetter(ExecState* exec, JSValue slotBase, const Iden
JSValue JSHTMLDocument::all(ExecState* exec) const
{
// If "all" has been overwritten, return the overwritten value
- JSValue v = getDirect(Identifier(exec, "all"));
+ JSValue v = getDirect(exec->globalData(), Identifier(exec, "all"));
if (v)
return v;
diff --git a/Source/WebCore/bindings/js/JSImageConstructor.h b/Source/WebCore/bindings/js/JSImageConstructor.h
index 654e223..4ef405d 100644
--- a/Source/WebCore/bindings/js/JSImageConstructor.h
+++ b/Source/WebCore/bindings/js/JSImageConstructor.h
@@ -29,7 +29,7 @@ namespace WebCore {
public:
JSImageConstructor(JSC::ExecState*, JSDOMGlobalObject*);
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
diff --git a/Source/WebCore/bindings/js/JSImageDataCustom.cpp b/Source/WebCore/bindings/js/JSImageDataCustom.cpp
index a92ed47..fb955b1 100644
--- a/Source/WebCore/bindings/js/JSImageDataCustom.cpp
+++ b/Source/WebCore/bindings/js/JSImageDataCustom.cpp
@@ -41,15 +41,15 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, ImageData* imageD
if (!imageData)
return jsNull();
- DOMObject* wrapper = getCachedDOMObjectWrapper(exec, imageData);
+ JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), imageData);
if (wrapper)
return wrapper;
wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, ImageData, imageData);
Identifier dataName(exec, "data");
static const ClassInfo cpaClassInfo = { "CanvasPixelArray", &JSByteArray::Base::s_info, 0, 0 };
- DEFINE_STATIC_LOCAL(RefPtr<Structure>, cpaStructure, (JSByteArray::createStructure(exec->globalData(), jsNull(), &cpaClassInfo)));
- wrapper->putDirect(exec->globalData(), dataName, new (exec) JSByteArray(exec, cpaStructure, imageData->data()->data()), DontDelete | ReadOnly);
+ DEFINE_STATIC_LOCAL(Strong<Structure>, cpaStructure, (exec->globalData(), JSByteArray::createStructure(exec->globalData(), jsNull(), &cpaClassInfo)));
+ wrapper->putDirect(exec->globalData(), dataName, new (exec) JSByteArray(exec, cpaStructure.get(), imageData->data()->data()), DontDelete | ReadOnly);
exec->heap()->reportExtraMemoryCost(imageData->data()->length());
return wrapper;
diff --git a/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp b/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp
index d56251f..2453215 100644
--- a/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp
+++ b/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp
@@ -70,6 +70,7 @@ Node* InjectedScriptHost::scriptValueAsNode(ScriptValue value)
ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* state, Node* node)
{
+ JSLock lock(SilenceAssertionsOnly);
return ScriptValue(state->globalData(), toJS(state, node));
}
diff --git a/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp b/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp
index 1843cd2..b784e6a 100644
--- a/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp
+++ b/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp
@@ -85,14 +85,14 @@ InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState* scriptState
JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject());
JSObject* injectedScript = globalObject->injectedScript();
if (injectedScript)
- return InjectedScript(ScriptObject(scriptState, injectedScript));
+ return InjectedScript(ScriptObject(scriptState, injectedScript), m_inspectedStateAccessCheck);
- if (!canAccessInspectedWindow(scriptState))
+ if (!m_inspectedStateAccessCheck(scriptState))
return InjectedScript();
pair<long, ScriptObject> injectedScriptObject = injectScript(injectedScriptSource(), scriptState);
globalObject->setInjectedScript(injectedScriptObject.second.jsObject());
- InjectedScript result(injectedScriptObject.second);
+ InjectedScript result(injectedScriptObject.second, m_inspectedStateAccessCheck);
m_idToInjectedScript.set(injectedScriptObject.first, result);
return result;
}
diff --git a/Source/WebCore/bindings/js/JSMessageEventCustom.cpp b/Source/WebCore/bindings/js/JSMessageEventCustom.cpp
index b3dabae..9dfc70a 100644
--- a/Source/WebCore/bindings/js/JSMessageEventCustom.cpp
+++ b/Source/WebCore/bindings/js/JSMessageEventCustom.cpp
@@ -60,6 +60,8 @@ JSC::JSValue JSMessageEvent::initMessageEvent(JSC::ExecState* exec)
bool canBubbleArg = exec->argument(1).toBoolean(exec);
bool cancelableArg = exec->argument(2).toBoolean(exec);
PassRefPtr<SerializedScriptValue> dataArg = SerializedScriptValue::create(exec, exec->argument(3));
+ if (exec->hadException())
+ return jsUndefined();
const UString& originArg = exec->argument(4).toString(exec);
const UString& lastEventIdArg = exec->argument(5).toString(exec);
DOMWindow* sourceArg = toDOMWindow(exec->argument(6));
diff --git a/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp b/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
index 8df9304..9b06767 100644
--- a/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
@@ -27,7 +27,6 @@
#include "JSNamedNodeMap.h"
#include "JSNode.h"
-
#include "Element.h"
#include "NamedNodeMap.h"
@@ -35,6 +34,40 @@ using namespace JSC;
namespace WebCore {
+class JSNamedNodeMapOwner : public JSC::WeakHandleOwner {
+ virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::MarkStack&);
+ virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+};
+
+bool JSNamedNodeMapOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, MarkStack& markStack)
+{
+ JSNamedNodeMap* jsNamedNodeMap = static_cast<JSNamedNodeMap*>(handle.get().asCell());
+ if (!jsNamedNodeMap->hasCustomProperties())
+ return false;
+ Element* element = jsNamedNodeMap->impl()->element();
+ if (!element)
+ return false;
+ return markStack.containsOpaqueRoot(root(element));
+}
+
+void JSNamedNodeMapOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+ JSNamedNodeMap* jsNamedNodeMap = static_cast<JSNamedNodeMap*>(handle.get().asCell());
+ DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);
+ uncacheWrapper(world, jsNamedNodeMap->impl(), jsNamedNodeMap);
+}
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld*, NamedNodeMap*)
+{
+ DEFINE_STATIC_LOCAL(JSNamedNodeMapOwner, jsNamedNodeMapOwner, ());
+ return &jsNamedNodeMapOwner;
+}
+
+inline void* wrapperContext(DOMWrapperWorld* world, NamedNodeMap*)
+{
+ return world;
+}
+
bool JSNamedNodeMap::canGetItemsForName(ExecState*, NamedNodeMap* impl, const Identifier& propertyName)
{
return impl->getNamedItem(identifierToString(propertyName));
@@ -50,10 +83,19 @@ void JSNamedNodeMap::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
- // Mark the element so that this will work to access the attribute even if the last
- // other reference goes away.
- if (Element* element = impl()->element())
- markDOMNodeWrapper(markStack, element->document(), element);
+ // We need to keep the wrapper for our underlying NamedNodeMap's element
+ // alive because NamedNodeMap and Attr rely on the element for data, and
+ // don't know how to keep it alive correctly.
+ // FIXME: Fix this lifetime issue in the DOM, and remove this.
+ Element* element = impl()->element();
+ if (!element)
+ return;
+ markStack.addOpaqueRoot(root(element));
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, NamedNodeMap* impl)
+{
+ return wrap<JSNamedNodeMap>(exec, globalObject, impl);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNavigatorCustom.cpp b/Source/WebCore/bindings/js/JSNavigatorCustom.cpp
index c8429ed..26e93e3 100644
--- a/Source/WebCore/bindings/js/JSNavigatorCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNavigatorCustom.cpp
@@ -23,7 +23,13 @@
#include "config.h"
#include "JSNavigator.h"
+<<<<<<< HEAD
#include "ExceptionCode.h"
+=======
+#include "CallbackFunction.h"
+#include "JSNavigatorUserMediaErrorCallback.h"
+#include "JSNavigatorUserMediaSuccessCallback.h"
+>>>>>>> WebKit.org at r84325
#include "Navigator.h"
#include <runtime/InternalFunction.h>
@@ -44,6 +50,7 @@ void JSNavigator::markChildren(MarkStack& markStack)
markDOMObjectWrapper(markStack, globalData, impl()->optionalGeolocation());
}
+<<<<<<< HEAD
#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED)
JSC::JSValue WebCore::JSNavigator::isApplicationInstalled(JSC::ExecState* exec)
@@ -75,5 +82,28 @@ JSC::JSValue WebCore::JSNavigator::isApplicationInstalled(JSC::ExecState* exec)
}
#endif
+=======
+#if ENABLE(MEDIA_STREAM)
+JSValue JSNavigator::webkitGetUserMedia(ExecState* exec)
+{
+ // Arguments: Options, successCallback, (optional)errorCallback
+
+ String options = ustringToString(exec->argument(0).toString(exec));
+ if (exec->hadException())
+ return jsUndefined();
+
+ RefPtr<NavigatorUserMediaSuccessCallback> successCallback = createFunctionOnlyCallback<JSNavigatorUserMediaSuccessCallback>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(1));
+ if (exec->hadException())
+ return jsUndefined();
+
+ RefPtr<NavigatorUserMediaErrorCallback> errorCallback = createFunctionOnlyCallback<JSNavigatorUserMediaErrorCallback>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(2), CallbackAllowUndefined);
+ if (exec->hadException())
+ return jsUndefined();
+
+ m_impl->webkitGetUserMedia(options, successCallback.release(), errorCallback.release());
+ return jsUndefined();
+}
+#endif // ENABLE(MEDIA_STREAM)
+>>>>>>> WebKit.org at r84325
}
diff --git a/Source/WebCore/bindings/js/JSNodeCustom.cpp b/Source/WebCore/bindings/js/JSNodeCustom.cpp
index 17f57f4..d305be7 100644
--- a/Source/WebCore/bindings/js/JSNodeCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeCustom.cpp
@@ -35,7 +35,15 @@
#include "Entity.h"
#include "EntityReference.h"
#include "ExceptionCode.h"
+#include "HTMLAudioElement.h"
+#include "HTMLCanvasElement.h"
#include "HTMLElement.h"
+#include "HTMLFrameElementBase.h"
+#include "HTMLImageElement.h"
+#include "HTMLLinkElement.h"
+#include "HTMLNames.h"
+#include "HTMLScriptElement.h"
+#include "HTMLStyleElement.h"
#include "JSAttr.h"
#include "JSCDATASection.h"
#include "JSComment.h"
@@ -55,6 +63,8 @@
#include "Notation.h"
#include "ProcessingInstruction.h"
#include "RegisteredEventListener.h"
+#include "StyleSheet.h"
+#include "StyledElement.h"
#include "Text.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
@@ -68,6 +78,114 @@ using namespace JSC;
namespace WebCore {
+using namespace HTMLNames;
+
+static bool isObservable(JSNode* jsNode, Node* node, DOMWrapperWorld* world)
+{
+ // Certain conditions implicitly make existence of a JS DOM node wrapper observable
+ // through the DOM, even if no explicit reference to it remains.
+
+ // The DOM doesn't know how to keep a tree of nodes alive without the root
+ // being explicitly referenced. So, we artificially treat the root of
+ // every tree as observable.
+ // FIXME: Resolve this lifetime issue in the DOM, and remove this inefficiency.
+ if (!node->parentNode())
+ return true;
+
+ // If a node is in the document, and its wrapper has custom properties,
+ // the wrapper is observable because future access to the node through the
+ // DOM must reflect those properties.
+ if (jsNode->hasCustomProperties())
+ return true;
+
+ // If a node is in the document, and has event listeners, its wrapper is
+ // observable because its wrapper is responsible for marking those event listeners.
+ if (node->hasEventListeners())
+ return true;
+
+ // If a node owns another object with a wrapper with custom properties,
+ // the wrapper must be treated as observable, because future access to
+ // those objects through the DOM must reflect those properties.
+ // FIXME: It would be better if this logic could be in the node next to
+ // the custom markChildren functions rather than here.
+ // Note that for some compound objects like stylesheets and CSSStyleDeclarations,
+ // we don't descend to check children for custom properties, and just conservatively
+ // keep the node wrappers protecting them alive.
+ if (node->isElementNode()) {
+ if (node->isStyledElement()) {
+ if (CSSMutableStyleDeclaration* style = static_cast<StyledElement*>(node)->inlineStyleDecl()) {
+ if (world->m_wrappers.get(style))
+ return true;
+ }
+ }
+ if (static_cast<Element*>(node)->hasTagName(canvasTag)) {
+ if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) {
+ if (JSDOMWrapper* wrapper = world->m_wrappers.get(context).get()) {
+ if (wrapper->hasCustomProperties())
+ return true;
+ }
+ }
+ } else if (static_cast<Element*>(node)->hasTagName(linkTag)) {
+ if (StyleSheet* sheet = static_cast<HTMLLinkElement*>(node)->sheet()) {
+ if (world->m_wrappers.get(sheet))
+ return true;
+ }
+ } else if (static_cast<Element*>(node)->hasTagName(styleTag)) {
+ if (StyleSheet* sheet = static_cast<HTMLStyleElement*>(node)->sheet()) {
+ if (world->m_wrappers.get(sheet))
+ return true;
+ }
+ }
+ } else if (node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
+ if (StyleSheet* sheet = static_cast<ProcessingInstruction*>(node)->sheet()) {
+ if (world->m_wrappers.get(sheet))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static inline bool isReachableFromDOM(JSNode* jsNode, Node* node, DOMWrapperWorld* world, MarkStack& markStack)
+{
+ if (!node->inDocument()) {
+ // If a wrapper is the last reference to an image or script element
+ // that is loading but not in the document, the wrapper is observable
+ // because it is the only thing keeping the image element alive, and if
+ // the image element is destroyed, its load event will not fire.
+ // FIXME: The DOM should manage this issue without the help of JavaScript wrappers.
+ if (node->hasTagName(imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())
+ return true;
+ if (node->hasTagName(scriptTag) && !static_cast<HTMLScriptElement*>(node)->haveFiredLoadEvent())
+ return true;
+ #if ENABLE(VIDEO)
+ if (node->hasTagName(audioTag) && !static_cast<HTMLAudioElement*>(node)->paused())
+ return true;
+ #endif
+
+ // If a node is firing event listeners, its wrapper is observable because
+ // its wrapper is responsible for marking those event listeners.
+ if (node->isFiringEventListeners())
+ return true;
+ }
+
+ return isObservable(jsNode, node, world) && markStack.containsOpaqueRoot(root(node));
+}
+
+bool JSNodeOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, MarkStack& markStack)
+{
+ JSNode* jsNode = static_cast<JSNode*>(handle.get().asCell());
+ DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);
+ return isReachableFromDOM(jsNode, jsNode->impl(), world, markStack);
+}
+
+void JSNodeOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+ JSNode* jsNode = static_cast<JSNode*>(handle.get().asCell());
+ DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);
+ uncacheWrapper(world, jsNode->impl(), jsNode);
+}
+
JSValue JSNode::insertBefore(ExecState* exec)
{
Node* imp = static_cast<Node*>(impl());
@@ -124,47 +242,13 @@ void JSNode::markChildren(MarkStack& markStack)
Node* node = m_impl.get();
node->markJSEventListeners(markStack);
- // Nodes in the document are kept alive by JSDocument::mark, so, if we're in
- // the document, we need to mark the document, but we don't need to explicitly
- // mark any other nodes.
- if (node->inDocument()) {
- // FIXME: Do we really want to call a virtual function, ownerDocument here,
- // when the non-virtual inline function, document, is so much faster?!
- if (Document* doc = node->ownerDocument())
- markDOMNodeWrapper(markStack, doc, doc);
- return;
- }
-
- // This is a node outside the document.
- // Find the the root, and the highest ancestor with a wrapper.
- Node* root = node;
- Node* outermostNodeWithWrapper = node;
- for (Node* current = m_impl.get(); current; current = current->parentNode()) {
- root = current;
- if (hasCachedDOMNodeWrapperUnchecked(current->document(), current))
- outermostNodeWithWrapper = current;
- }
-
- // Only nodes that have no ancestors with wrappers mark the subtree. In the common
- // case, the root of the detached subtree has a wrapper, so the tree will only
- // get marked once. Nodes that aren't outermost need to mark the outermost
- // in case it is otherwise unreachable.
- // FIXME: In the non-common case of root not having a wrapper, this is still an O(n^2) algorithm,
- // as we will traverse the whole tree as many times as there are nodes with wrappers in it.
- if (node != outermostNodeWithWrapper) {
- markDOMNodeWrapper(markStack, m_impl->document(), outermostNodeWithWrapper);
- return;
- }
-
- // Mark the whole tree subtree.
- for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode())
- markDOMNodeWrapper(markStack, m_impl->document(), nodeToMark);
+ markStack.addOpaqueRoot(root(node));
}
static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
{
ASSERT(node);
- ASSERT(!getCachedDOMNodeWrapper(exec, node->document(), node));
+ ASSERT(!getCachedWrapper(currentWorld(exec), node));
JSNode* wrapper;
switch (node->nodeType()) {
diff --git a/Source/WebCore/bindings/js/JSNodeCustom.h b/Source/WebCore/bindings/js/JSNodeCustom.h
index 9d06ae6..cefa3e3 100644
--- a/Source/WebCore/bindings/js/JSNodeCustom.h
+++ b/Source/WebCore/bindings/js/JSNodeCustom.h
@@ -31,16 +31,45 @@
namespace WebCore {
-inline JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node)
+class JSNodeOwner : public JSC::WeakHandleOwner {
+ virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::MarkStack&);
+ virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+};
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld*, Node*)
+{
+ DEFINE_STATIC_LOCAL(JSNodeOwner, jsNodeOwner, ());
+ return &jsNodeOwner;
+}
+
+inline void* wrapperContext(DOMWrapperWorld* world, Node*)
+{
+ return world;
+}
+
+inline JSDOMWrapper* getInlineCachedWrapper(DOMWrapperWorld* world, Node* node)
+{
+ if (!world->isNormal())
+ return 0;
+ return node->wrapper();
+}
+
+inline bool setInlineCachedWrapper(DOMWrapperWorld* world, Node* node, JSDOMWrapper* wrapper)
{
- if (currentWorld(exec)->isNormal()) {
- ASSERT(node->wrapper() == (document ? document->getWrapperCache(currentWorld(exec))->get(node) : domObjectWrapperMapFor(exec).get(node)));
- return static_cast<JSNode*>(node->wrapper());
- }
+ if (!world->isNormal())
+ return false;
+ ASSERT(!node->wrapper());
+ node->setWrapper(*world->globalData(), wrapper, wrapperOwner(world, node), wrapperContext(world, node));
+ return true;
+}
- if (document)
- return document->getWrapperCache(currentWorld(exec))->get(node);
- return static_cast<JSNode*>(domObjectWrapperMapFor(exec).get(node));
+inline bool clearInlineCachedWrapper(DOMWrapperWorld* world, Node* node, JSDOMWrapper* wrapper)
+{
+ if (!world->isNormal())
+ return false;
+ ASSERT_UNUSED(wrapper, node->wrapper() == wrapper);
+ node->clearWrapper();
+ return true;
}
JSC::JSValue createWrapper(JSC::ExecState*, JSDOMGlobalObject*, Node*);
@@ -50,13 +79,23 @@ inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject,
if (!node)
return JSC::jsNull();
- JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node);
+ JSNode* wrapper = static_cast<JSNode*>(getCachedWrapper(currentWorld(exec), node));
if (wrapper)
return wrapper;
return createWrapper(exec, globalObject, node);
}
+static inline Node* root(Node* node)
+{
+ if (node->inDocument())
+ return node->document();
+
+ while (node->parentNode())
+ node = node->parentNode();
+ return node;
+}
+
}
#endif // JSDOMNodeCustom_h
diff --git a/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp b/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp
index 1cf72a5..927b1a3 100644
--- a/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp
+++ b/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp
@@ -32,21 +32,16 @@ using namespace JSC;
ASSERT_CLASS_FITS_IN_CELL(JSNodeFilterCondition);
-JSNodeFilterCondition::JSNodeFilterCondition(JSValue filter)
- : m_filter(filter)
+JSNodeFilterCondition::JSNodeFilterCondition(JSGlobalData& globalData, NodeFilter* owner, JSValue filter)
+ : m_filter(globalData, filter, &m_weakOwner, owner)
{
}
-void JSNodeFilterCondition::markAggregate(MarkStack& markStack)
-{
- markStack.append(&m_filter);
-}
-
short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) const
{
JSLock lock(SilenceAssertionsOnly);
- if (!m_filter->isObject())
+ if (!m_filter.isObject())
return NodeFilter::FILTER_ACCEPT;
// The exec argument here should only be null if this was called from a
@@ -62,7 +57,7 @@ short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode)
CallData callData;
CallType callType = getCallData(function, callData);
if (callType == CallTypeNone) {
- function = m_filter->get(exec, Identifier(exec, "acceptNode"));
+ function = m_filter.get().get(exec, Identifier(exec, "acceptNode"));
callType = getCallData(function, callData);
if (callType == CallTypeNone) {
throwError(exec, createTypeError(exec, "NodeFilter object does not have an acceptNode function"));
@@ -88,4 +83,9 @@ short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode)
return intResult;
}
+bool JSNodeFilterCondition::WeakOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, MarkStack& markStack)
+{
+ return markStack.containsOpaqueRoot(context);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeFilterCondition.h b/Source/WebCore/bindings/js/JSNodeFilterCondition.h
index 14b0c1d..80148f1 100644
--- a/Source/WebCore/bindings/js/JSNodeFilterCondition.h
+++ b/Source/WebCore/bindings/js/JSNodeFilterCondition.h
@@ -21,27 +21,32 @@
#define JSNodeFilterCondition_h
#include "NodeFilterCondition.h"
+#include <heap/Weak.h>
#include <runtime/JSValue.h>
#include <wtf/PassRefPtr.h>
namespace WebCore {
class Node;
+ class NodeFilter;
class JSNodeFilterCondition : public NodeFilterCondition {
public:
- static PassRefPtr<JSNodeFilterCondition> create(JSC::JSValue filter)
+ static PassRefPtr<JSNodeFilterCondition> create(JSC::JSGlobalData& globalData, NodeFilter* owner, JSC::JSValue filter)
{
- return adoptRef(new JSNodeFilterCondition(filter));
+ return adoptRef(new JSNodeFilterCondition(globalData, owner, filter));
}
private:
- JSNodeFilterCondition(JSC::JSValue filter);
+ JSNodeFilterCondition(JSC::JSGlobalData&, NodeFilter* owner, JSC::JSValue filter);
virtual short acceptNode(ScriptState*, Node*) const;
- virtual void markAggregate(JSC::MarkStack&);
- mutable JSC::DeprecatedPtr<JSC::Unknown> m_filter;
+ class WeakOwner : public JSC::WeakHandleOwner {
+ virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::MarkStack&);
+ };
+ WeakOwner m_weakOwner;
+ mutable JSC::Weak<JSC::Unknown> m_filter;
};
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp b/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
index bc79e99..ad4aa7e 100644
--- a/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
@@ -39,15 +39,17 @@ namespace WebCore {
void JSNodeFilter::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
- impl()->markAggregate(markStack);
+ markStack.addOpaqueRoot(impl());
}
-PassRefPtr<NodeFilter> toNodeFilter(JSValue value)
+PassRefPtr<NodeFilter> toNodeFilter(JSGlobalData& globalData, JSValue value)
{
if (value.inherits(&JSNodeFilter::s_info))
return static_cast<JSNodeFilter*>(asObject(value))->impl();
- return NodeFilter::create(JSNodeFilterCondition::create(value));
+ RefPtr<NodeFilter> result = NodeFilter::create();
+ result->setCondition(JSNodeFilterCondition::create(globalData, result.get(), value));
+ return result.release();
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp b/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp
index 7c858e5..77f2dc3 100644
--- a/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp
@@ -34,7 +34,7 @@ void JSNodeIterator::markChildren(MarkStack& markStack)
Base::markChildren(markStack);
if (NodeFilter* filter = m_impl->filter())
- filter->markAggregate(markStack);
+ markStack.addOpaqueRoot(filter);
}
}
diff --git a/Source/WebCore/bindings/js/JSNodeListCustom.cpp b/Source/WebCore/bindings/js/JSNodeListCustom.cpp
index c81914c..a52ac64 100644
--- a/Source/WebCore/bindings/js/JSNodeListCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeListCustom.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "JSNodeList.h"
+#include "DynamicNodeList.h"
#include "JSNode.h"
#include "Node.h"
#include "NodeList.h"
@@ -35,6 +36,44 @@ using namespace JSC;
namespace WebCore {
+class JSNodeListOwner : public JSC::WeakHandleOwner {
+ virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::MarkStack&);
+ virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);
+};
+
+bool JSNodeListOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, MarkStack& markStack)
+{
+ JSNodeList* jsNodeList = static_cast<JSNodeList*>(handle.get().asCell());
+ if (!jsNodeList->hasCustomProperties())
+ return false;
+ if (!jsNodeList->impl()->isDynamicNodeList())
+ return false;
+ return markStack.containsOpaqueRoot(root(static_cast<DynamicNodeList*>(jsNodeList->impl())->rootNode()));
+}
+
+void JSNodeListOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+ JSNodeList* jsNodeList = static_cast<JSNodeList*>(handle.get().asCell());
+ DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);
+ uncacheWrapper(world, jsNodeList->impl(), jsNodeList);
+}
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld*, NodeList*)
+{
+ DEFINE_STATIC_LOCAL(JSNodeListOwner, jsNodeListOwner, ());
+ return &jsNodeListOwner;
+}
+
+inline void* wrapperContext(DOMWrapperWorld* world, NodeList*)
+{
+ return world;
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, NodeList* impl)
+{
+ return wrap<JSNodeList>(exec, globalObject, impl);
+}
+
// Need to support call so that list(0) works.
static EncodedJSValue JSC_HOST_CALL callNodeList(ExecState* exec)
{
diff --git a/Source/WebCore/bindings/js/JSOptionConstructor.h b/Source/WebCore/bindings/js/JSOptionConstructor.h
index 8a18007..3317978 100644
--- a/Source/WebCore/bindings/js/JSOptionConstructor.h
+++ b/Source/WebCore/bindings/js/JSOptionConstructor.h
@@ -30,7 +30,7 @@ namespace WebCore {
public:
JSOptionConstructor(JSC::ExecState*, JSDOMGlobalObject*);
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
diff --git a/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp b/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
index dec4be0..defbd5f 100644
--- a/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
+++ b/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
@@ -28,6 +28,7 @@
#include "JSSVGElementInstance.h"
#if ENABLE(SVG)
+#include "JSNode.h"
#include "SVGElementInstance.h"
namespace WebCore {
@@ -35,9 +36,7 @@ namespace WebCore {
void JSSVGElementInstance::markChildren(JSC::MarkStack& markStack)
{
Base::markChildren(markStack);
-
- // Mark the wrapper for our corresponding element, so it can mark its event handlers.
- markDOMNodeWrapper(markStack, impl()->correspondingElement()->document(), impl()->correspondingElement());
+ markStack.addOpaqueRoot(root(impl()->correspondingElement()));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp b/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
index f0aa86b..dc5eadd 100644
--- a/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
+++ b/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
@@ -63,7 +63,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, SVGPathSeg* objec
if (!object)
return jsNull();
- if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object))
+ if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), object))
return wrapper;
switch (object->pathSegType()) {
diff --git a/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp b/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
index 04c6561..66e5244 100644
--- a/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
+++ b/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
@@ -40,7 +40,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, StyleSheet* style
if (!styleSheet)
return jsNull();
- DOMObject* wrapper = getCachedDOMObjectWrapper(exec, styleSheet);
+ JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), styleSheet);
if (wrapper)
return wrapper;
diff --git a/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp b/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp
index 0c1947f..fc64900 100644
--- a/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp
@@ -34,7 +34,7 @@ void JSTreeWalker::markChildren(MarkStack& markStack)
Base::markChildren(markStack);
if (NodeFilter* filter = m_impl->filter())
- filter->markAggregate(markStack);
+ markStack.addOpaqueRoot(filter);
}
}
diff --git a/Source/WebCore/bindings/js/JSWorkerContextBase.cpp b/Source/WebCore/bindings/js/JSWorkerContextBase.cpp
index c6f86b5..cbf01b7 100644
--- a/Source/WebCore/bindings/js/JSWorkerContextBase.cpp
+++ b/Source/WebCore/bindings/js/JSWorkerContextBase.cpp
@@ -31,6 +31,7 @@
#include "JSWorkerContextBase.h"
+#include "DOMWrapperWorld.h"
#include "JSDedicatedWorkerContext.h"
#include "JSSharedWorkerContext.h"
#include "JSWorkerContext.h"
@@ -44,8 +45,8 @@ ASSERT_CLASS_FITS_IN_CELL(JSWorkerContextBase);
const ClassInfo JSWorkerContextBase::s_info = { "WorkerContext", &JSDOMGlobalObject::s_info, 0, 0 };
-JSWorkerContextBase::JSWorkerContextBase(NonNullPassRefPtr<JSC::Structure> structure, PassRefPtr<WorkerContext> impl)
- : JSDOMGlobalObject(structure, normalWorld(*impl->script()->globalData()), this)
+JSWorkerContextBase::JSWorkerContextBase(JSC::JSGlobalData& globalData, JSC::Structure* structure, PassRefPtr<WorkerContext> impl)
+ : JSDOMGlobalObject(globalData, structure, normalWorld(globalData), this)
, m_impl(impl)
{
ASSERT(inherits(&s_info));
diff --git a/Source/WebCore/bindings/js/JSWorkerContextBase.h b/Source/WebCore/bindings/js/JSWorkerContextBase.h
index b9c234a..af68b58 100644
--- a/Source/WebCore/bindings/js/JSWorkerContextBase.h
+++ b/Source/WebCore/bindings/js/JSWorkerContextBase.h
@@ -41,7 +41,7 @@ namespace WebCore {
class JSWorkerContextBase : public JSDOMGlobalObject {
typedef JSDOMGlobalObject Base;
public:
- JSWorkerContextBase(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<WorkerContext>);
+ JSWorkerContextBase(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<WorkerContext>);
virtual ~JSWorkerContextBase();
static const JSC::ClassInfo s_info;
@@ -49,7 +49,7 @@ namespace WebCore {
WorkerContext* impl() const { return m_impl.get(); }
virtual ScriptExecutionContext* scriptExecutionContext() const;
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
diff --git a/Source/WebCore/bindings/js/JSWorkerContextCustom.cpp b/Source/WebCore/bindings/js/JSWorkerContextCustom.cpp
index 8c1caef..1103d0b 100644
--- a/Source/WebCore/bindings/js/JSWorkerContextCustom.cpp
+++ b/Source/WebCore/bindings/js/JSWorkerContextCustom.cpp
@@ -122,7 +122,8 @@ JSValue JSWorkerContext::importScripts(ExecState* exec)
JSValue JSWorkerContext::setTimeout(ExecState* exec)
{
- OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec));
+ // FIXME: Should we enforce a Content-Security-Policy on workers?
+ OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), 0);
if (exec->hadException())
return jsUndefined();
int delay = exec->argument(1).toInt32(exec);
@@ -131,7 +132,8 @@ JSValue JSWorkerContext::setTimeout(ExecState* exec)
JSValue JSWorkerContext::setInterval(ExecState* exec)
{
- OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec));
+ // FIXME: Should we enforce a Content-Security-Policy on workers?
+ OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), 0);
if (exec->hadException())
return jsUndefined();
int delay = exec->argument(1).toInt32(exec);
diff --git a/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
index 1d6f1cb..eba5db7 100644
--- a/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
+++ b/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
@@ -64,10 +64,8 @@ void JSXMLHttpRequest::markChildren(MarkStack& markStack)
if (Document* responseDocument = m_impl->optionalResponseXML())
markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), responseDocument);
-#if ENABLE(WEBGL) || ENABLE(BLOB)
if (ArrayBuffer* responseArrayBuffer = m_impl->optionalResponseArrayBuffer())
markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), responseArrayBuffer);
-#endif
#if ENABLE(XHR_RESPONSE_BLOB)
if (Blob* responseBlob = m_impl->optionalResponseBlob())
@@ -124,10 +122,8 @@ JSValue JSXMLHttpRequest::send(ExecState* exec)
impl()->send(toBlob(val), ec);
else if (val.inherits(&JSDOMFormData::s_info))
impl()->send(toDOMFormData(val), ec);
-#if ENABLE(WEBGL) || ENABLE(BLOB)
else if (val.inherits(&JSArrayBuffer::s_info))
impl()->send(toArrayBuffer(val), ec);
-#endif
else
impl()->send(ustringToString(val.toString(exec)), ec);
}
@@ -189,7 +185,6 @@ JSValue JSXMLHttpRequest::response(ExecState* exec) const
#endif
case XMLHttpRequest::ResponseTypeArrayBuffer:
-#if ENABLE(WEBGL) || ENABLE(BLOB)
{
ExceptionCode ec = 0;
ArrayBuffer* arrayBuffer = impl()->responseArrayBuffer(ec);
@@ -199,9 +194,6 @@ JSValue JSXMLHttpRequest::response(ExecState* exec) const
}
return toJS(exec, globalObject(), arrayBuffer);
}
-#else
- return jsUndefined();
-#endif
}
return jsUndefined();
diff --git a/Source/WebCore/bindings/js/ScheduledAction.cpp b/Source/WebCore/bindings/js/ScheduledAction.cpp
index f623017..b8a623b 100644
--- a/Source/WebCore/bindings/js/ScheduledAction.cpp
+++ b/Source/WebCore/bindings/js/ScheduledAction.cpp
@@ -24,6 +24,7 @@
#include "config.h"
#include "ScheduledAction.h"
+#include "ContentSecurityPolicy.h"
#include "DOMWindow.h"
#include "Document.h"
#include "Frame.h"
@@ -46,11 +47,13 @@ using namespace JSC;
namespace WebCore {
-PassOwnPtr<ScheduledAction> ScheduledAction::create(ExecState* exec, DOMWrapperWorld* isolatedWorld)
+PassOwnPtr<ScheduledAction> ScheduledAction::create(ExecState* exec, DOMWrapperWorld* isolatedWorld, ContentSecurityPolicy* policy)
{
JSValue v = exec->argument(0);
CallData callData;
if (getCallData(v, callData) == CallTypeNone) {
+ if (policy && !policy->allowEval())
+ return 0;
UString string = v.toString(exec);
if (exec->hadException())
return 0;
@@ -67,7 +70,7 @@ ScheduledAction::ScheduledAction(ExecState* exec, JSValue function, DOMWrapperWo
// setTimeout(function, interval, arg0, arg1...).
// Start at 2 to skip function and interval.
for (size_t i = 2; i < exec->argumentCount(); ++i)
- m_args.append(Global<JSC::Unknown>(exec->globalData(), exec->argument(i)));
+ m_args.append(Strong<JSC::Unknown>(exec->globalData(), exec->argument(i)));
}
void ScheduledAction::execute(ScriptExecutionContext* context)
diff --git a/Source/WebCore/bindings/js/ScheduledAction.h b/Source/WebCore/bindings/js/ScheduledAction.h
index 3adc185..1595758 100644
--- a/Source/WebCore/bindings/js/ScheduledAction.h
+++ b/Source/WebCore/bindings/js/ScheduledAction.h
@@ -22,7 +22,7 @@
#include "JSDOMBinding.h"
#include "PlatformString.h"
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <runtime/JSCell.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
@@ -34,6 +34,7 @@ namespace JSC {
namespace WebCore {
class Document;
+ class ContentSecurityPolicy;
class ScriptExecutionContext;
class WorkerContext;
@@ -44,7 +45,7 @@ namespace WebCore {
class ScheduledAction {
WTF_MAKE_NONCOPYABLE(ScheduledAction); WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<ScheduledAction> create(JSC::ExecState*, DOMWrapperWorld* isolatedWorld);
+ static PassOwnPtr<ScheduledAction> create(JSC::ExecState*, DOMWrapperWorld* isolatedWorld, ContentSecurityPolicy*);
void execute(ScriptExecutionContext*);
@@ -63,8 +64,8 @@ namespace WebCore {
void execute(WorkerContext*);
#endif
- JSC::Global<JSC::Unknown> m_function;
- Vector<JSC::Global<JSC::Unknown> > m_args;
+ JSC::Strong<JSC::Unknown> m_function;
+ Vector<JSC::Strong<JSC::Unknown> > m_args;
String m_code;
RefPtr<DOMWrapperWorld> m_isolatedWorld;
};
diff --git a/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp b/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
index 5a467f2..1f0953b 100644
--- a/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
+++ b/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
@@ -54,7 +54,7 @@ ScriptCachedFrameData::ScriptCachedFrameData(Frame* frame)
ScriptController::ShellMap::iterator windowShellsEnd = windowShells.end();
for (ScriptController::ShellMap::iterator iter = windowShells.begin(); iter != windowShellsEnd; ++iter) {
JSDOMWindow* window = iter->second->window();
- m_windows.add(iter->first.get(), Global<JSDOMWindow>(window->globalData(), window));
+ m_windows.add(iter->first.get(), Strong<JSDOMWindow>(window->globalData(), window));
m_domWindow = window->impl();
}
diff --git a/Source/WebCore/bindings/js/ScriptCachedFrameData.h b/Source/WebCore/bindings/js/ScriptCachedFrameData.h
index 08874d5..a85e16f 100644
--- a/Source/WebCore/bindings/js/ScriptCachedFrameData.h
+++ b/Source/WebCore/bindings/js/ScriptCachedFrameData.h
@@ -32,7 +32,8 @@
#ifndef ScriptCachedFrameData_h
#define ScriptCachedFrameData_h
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
+#include <wtf/HashMap.h>
namespace WebCore {
class Frame;
@@ -42,7 +43,7 @@ namespace WebCore {
class ScriptCachedFrameData {
WTF_MAKE_NONCOPYABLE(ScriptCachedFrameData); WTF_MAKE_FAST_ALLOCATED;
- typedef HashMap< RefPtr<DOMWrapperWorld>, JSC::Global<JSDOMWindow> > JSDOMWindowSet;
+ typedef HashMap< RefPtr<DOMWrapperWorld>, JSC::Strong<JSDOMWindow> > JSDOMWindowSet;
public:
ScriptCachedFrameData(Frame*);
diff --git a/Source/WebCore/bindings/js/ScriptController.cpp b/Source/WebCore/bindings/js/ScriptController.cpp
index 4b0f44f..45c4faa 100644
--- a/Source/WebCore/bindings/js/ScriptController.cpp
+++ b/Source/WebCore/bindings/js/ScriptController.cpp
@@ -108,8 +108,8 @@ void ScriptController::destroyWindowShell(DOMWrapperWorld* world)
JSDOMWindowShell* ScriptController::createWindowShell(DOMWrapperWorld* world)
{
ASSERT(!m_windowShells.contains(world));
- Global<JSDOMWindowShell> windowShell(*world->globalData(), new JSDOMWindowShell(m_frame->domWindow(), world));
- Global<JSDOMWindowShell> windowShell2(windowShell);
+ Strong<JSDOMWindowShell> windowShell(*world->globalData(), new JSDOMWindowShell(m_frame->domWindow(), world));
+ Strong<JSDOMWindowShell> windowShell2(windowShell);
m_windowShells.add(world, windowShell);
world->didCreateWindowShell(this);
return windowShell.get();
diff --git a/Source/WebCore/bindings/js/ScriptController.h b/Source/WebCore/bindings/js/ScriptController.h
index 2ec3872..7a132b3 100644
--- a/Source/WebCore/bindings/js/ScriptController.h
+++ b/Source/WebCore/bindings/js/ScriptController.h
@@ -25,7 +25,7 @@
#include "JSDOMWindowShell.h"
#include "ScriptControllerBase.h"
#include "ScriptInstance.h"
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <wtf/Forward.h>
#include <wtf/RefPtr.h>
@@ -64,7 +64,7 @@ typedef HashMap<void*, RefPtr<JSC::Bindings::RootObject> > RootObjectMap;
class ScriptController {
friend class ScriptCachedFrameData;
- typedef WTF::HashMap< RefPtr<DOMWrapperWorld>, JSC::Global<JSDOMWindowShell> > ShellMap;
+ typedef WTF::HashMap< RefPtr<DOMWrapperWorld>, JSC::Strong<JSDOMWindowShell> > ShellMap;
public:
ScriptController(Frame*);
diff --git a/Source/WebCore/bindings/js/ScriptDebugServer.cpp b/Source/WebCore/bindings/js/ScriptDebugServer.cpp
index 05c0f2c..88e685f 100644
--- a/Source/WebCore/bindings/js/ScriptDebugServer.cpp
+++ b/Source/WebCore/bindings/js/ScriptDebugServer.cpp
@@ -112,7 +112,7 @@ bool ScriptDebugServer::hasBreakpoint(intptr_t sourceID, const TextPosition0& po
if (lineNumber <= 0)
return false;
LineToBreakpointMap::const_iterator breakIt = it->second.find(lineNumber);
- if (breakIt == it->second.end() || !breakIt->second.enabled)
+ if (breakIt == it->second.end())
return false;
// An empty condition counts as no condition which is equivalent to "true".
@@ -189,7 +189,7 @@ void ScriptDebugServer::stepOutOfFunction()
m_doneProcessingDebuggerEvents = true;
}
-bool ScriptDebugServer::editScriptSource(const String&, const String&, String&)
+bool ScriptDebugServer::editScriptSource(const String&, const String&, String*)
{
// FIXME(40300): implement this.
return false;
@@ -214,7 +214,7 @@ void ScriptDebugServer::dispatchDidContinue(ScriptDebugListener* listener)
listener->didContinue();
}
-void ScriptDebugServer::dispatchDidParseSource(const ListenerSet& listeners, SourceProvider* sourceProvider, ScriptWorldType worldType)
+void ScriptDebugServer::dispatchDidParseSource(const ListenerSet& listeners, SourceProvider* sourceProvider, bool isContentScript)
{
String sourceID = ustringToString(JSC::UString::number(sourceProvider->asID()));
String url = ustringToString(sourceProvider->url());
@@ -225,7 +225,7 @@ void ScriptDebugServer::dispatchDidParseSource(const ListenerSet& listeners, Sou
Vector<ScriptDebugListener*> copy;
copyToVector(listeners, copy);
for (size_t i = 0; i < copy.size(); ++i)
- copy[i]->didParseSource(sourceID, url, data, lineOffset, columnOffset, worldType);
+ copy[i]->didParseSource(sourceID, url, data, lineOffset, columnOffset, isContentScript);
}
void ScriptDebugServer::dispatchFailedToParseSource(const ListenerSet& listeners, SourceProvider* sourceProvider, int errorLine, const String& errorMessage)
@@ -240,11 +240,9 @@ void ScriptDebugServer::dispatchFailedToParseSource(const ListenerSet& listeners
copy[i]->failedToParseSource(url, data, firstLine, errorLine, errorMessage);
}
-static ScriptWorldType currentWorldType(ExecState* exec)
+static bool isContentScript(ExecState* exec)
{
- if (currentWorld(exec) == mainThreadNormalWorld())
- return MAIN_WORLD;
- return EXTENSIONS_WORLD;
+ return currentWorld(exec) != mainThreadNormalWorld();
}
void ScriptDebugServer::detach(JSGlobalObject* globalObject)
@@ -275,10 +273,8 @@ void ScriptDebugServer::sourceParsed(ExecState* exec, SourceProvider* sourceProv
bool isError = errorLine != -1;
if (isError)
dispatchFailedToParseSource(*listeners, sourceProvider, errorLine, ustringToString(errorMessage));
- else {
- ScriptWorldType worldType = currentWorldType(exec);
- dispatchDidParseSource(*listeners, sourceProvider, worldType);
- }
+ else
+ dispatchDidParseSource(*listeners, sourceProvider, isContentScript(exec));
m_callingListeners = false;
}
diff --git a/Source/WebCore/bindings/js/ScriptDebugServer.h b/Source/WebCore/bindings/js/ScriptDebugServer.h
index e53cb4d..f6ac9a1 100644
--- a/Source/WebCore/bindings/js/ScriptDebugServer.h
+++ b/Source/WebCore/bindings/js/ScriptDebugServer.h
@@ -78,7 +78,7 @@ public:
void stepOverStatement();
void stepOutOfFunction();
- bool editScriptSource(const String& sourceID, const String& newContent, String& newSourceOrErrorMessage);
+ bool editScriptSource(const String& sourceID, const String& newContent, String* error);
void recompileAllJSFunctionsSoon();
virtual void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) = 0;
@@ -102,7 +102,7 @@ protected:
void dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptExecutionCallback callback);
void dispatchDidPause(ScriptDebugListener*);
void dispatchDidContinue(ScriptDebugListener*);
- void dispatchDidParseSource(const ListenerSet& listeners, JSC::SourceProvider*, enum ScriptWorldType);
+ void dispatchDidParseSource(const ListenerSet& listeners, JSC::SourceProvider*, bool isContentScript);
void dispatchFailedToParseSource(const ListenerSet& listeners, JSC::SourceProvider*, int errorLine, const String& errorMessage);
void createCallFrameAndPauseIfNeeded(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber);
diff --git a/Source/WebCore/bindings/js/ScriptGCEvent.cpp b/Source/WebCore/bindings/js/ScriptGCEvent.cpp
index dd027b4..b694c7c 100644
--- a/Source/WebCore/bindings/js/ScriptGCEvent.cpp
+++ b/Source/WebCore/bindings/js/ScriptGCEvent.cpp
@@ -34,7 +34,7 @@
#if ENABLE(INSPECTOR)
#include "JSDOMWindow.h"
-#include <runtime/Heap.h>
+#include <heap/Heap.h>
#include <runtime/JSGlobalData.h>
#include <wtf/CurrentTime.h>
diff --git a/Source/WebCore/bindings/js/ScriptObject.h b/Source/WebCore/bindings/js/ScriptObject.h
index c10bf18..eb02e9b 100644
--- a/Source/WebCore/bindings/js/ScriptObject.h
+++ b/Source/WebCore/bindings/js/ScriptObject.h
@@ -34,7 +34,7 @@
#include "ScriptState.h"
#include "ScriptValue.h"
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <runtime/JSObject.h>
namespace WebCore {
diff --git a/Source/WebCore/bindings/js/ScriptState.cpp b/Source/WebCore/bindings/js/ScriptState.cpp
index 8a7c9a5..a4b9793 100644
--- a/Source/WebCore/bindings/js/ScriptState.cpp
+++ b/Source/WebCore/bindings/js/ScriptState.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,8 +33,11 @@
#include "Frame.h"
#include "JSDOMWindowBase.h"
+#include "JSWorkerContext.h"
#include "Node.h"
#include "Page.h"
+#include "WorkerContext.h"
+#include "WorkerScriptController.h"
#include <interpreter/CallFrame.h>
#include <runtime/JSGlobalObject.h>
@@ -83,4 +86,11 @@ ScriptState* scriptStateFromPage(DOMWrapperWorld* world, Page* page)
return page->mainFrame()->script()->globalObject(world)->globalExec();
}
+#if ENABLE(WORKERS)
+ScriptState* scriptStateFromWorkerContext(WorkerContext* workerContext)
+{
+ return workerContext->script()->workerContextWrapper()->globalExec();
+}
+#endif
+
}
diff --git a/Source/WebCore/bindings/js/ScriptState.h b/Source/WebCore/bindings/js/ScriptState.h
index f27b306..cdc3fbf 100644
--- a/Source/WebCore/bindings/js/ScriptState.h
+++ b/Source/WebCore/bindings/js/ScriptState.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Google Inc.
+ * Copyright (c) 2008, 2011 Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,7 @@
#ifndef ScriptState_h
#define ScriptState_h
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <wtf/Noncopyable.h>
namespace JSC {
@@ -45,6 +45,7 @@ class DOMWrapperWorld;
class Frame;
class Node;
class Page;
+class WorkerContext;
// The idea is to expose "state-like" methods (hadException, and any other
// methods where ExecState just dips into globalData) of JSC::ExecState as a
@@ -59,7 +60,7 @@ public:
~ScriptStateProtectedPtr();
ScriptState* get() const;
private:
- JSC::Global<JSC::JSGlobalObject> m_globalObject;
+ JSC::Strong<JSC::JSGlobalObject> m_globalObject;
};
ScriptState* mainWorldScriptState(Frame*);
@@ -67,6 +68,10 @@ ScriptState* mainWorldScriptState(Frame*);
ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*);
ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*);
+#if ENABLE(WORKERS)
+ScriptState* scriptStateFromWorkerContext(WorkerContext*);
+#endif
+
} // namespace WebCore
#endif // ScriptState_h
diff --git a/Source/WebCore/bindings/js/ScriptValue.cpp b/Source/WebCore/bindings/js/ScriptValue.cpp
index 6fe6ea3..4f51ddb 100644
--- a/Source/WebCore/bindings/js/ScriptValue.cpp
+++ b/Source/WebCore/bindings/js/ScriptValue.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,7 +36,7 @@
#include <JavaScriptCore/APICast.h>
#include <JavaScriptCore/JSValueRef.h>
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <runtime/JSLock.h>
#include <runtime/UString.h>
@@ -55,6 +56,15 @@ bool ScriptValue::getString(ScriptState* scriptState, String& result) const
return true;
}
+String ScriptValue::toString(ScriptState* scriptState) const
+{
+ String result = ustringToString(m_value.get().toString(scriptState));
+ // Handle the case where an exception is thrown as part of invoking toString on the object.
+ if (scriptState->hadException())
+ scriptState->clearException();
+ return result;
+}
+
bool ScriptValue::isEqual(ScriptState* scriptState, const ScriptValue& anotherValue) const
{
if (hasNoValue())
@@ -90,14 +100,14 @@ bool ScriptValue::isFunction() const
return getCallData(m_value.get(), callData) != CallTypeNone;
}
-PassRefPtr<SerializedScriptValue> ScriptValue::serialize(ScriptState* scriptState)
+PassRefPtr<SerializedScriptValue> ScriptValue::serialize(ScriptState* scriptState, SerializationErrorMode throwExceptions)
{
- return SerializedScriptValue::create(scriptState, jsValue());
+ return SerializedScriptValue::create(scriptState, jsValue(), throwExceptions);
}
-ScriptValue ScriptValue::deserialize(ScriptState* scriptState, SerializedScriptValue* value)
+ScriptValue ScriptValue::deserialize(ScriptState* scriptState, SerializedScriptValue* value, SerializationErrorMode throwExceptions)
{
- return ScriptValue(scriptState->globalData(), value->deserialize(scriptState, scriptState->lexicalGlobalObject()));
+ return ScriptValue(scriptState->globalData(), value->deserialize(scriptState, scriptState->lexicalGlobalObject(), throwExceptions));
}
#if ENABLE(INSPECTOR)
diff --git a/Source/WebCore/bindings/js/ScriptValue.h b/Source/WebCore/bindings/js/ScriptValue.h
index 37cf243..fade830 100644
--- a/Source/WebCore/bindings/js/ScriptValue.h
+++ b/Source/WebCore/bindings/js/ScriptValue.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Google Inc. All rights reserved.
+ * Copyright (c) 2008, 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,8 +33,9 @@
#include "JSDOMBinding.h"
#include "PlatformString.h"
+#include "SerializedScriptValue.h"
#include "ScriptState.h"
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <runtime/JSValue.h>
#include <wtf/PassRefPtr.h>
@@ -45,24 +46,24 @@ class SerializedScriptValue;
class ScriptValue {
public:
- ScriptValue() : m_value(JSC::Global<JSC::Unknown>::EmptyValue) { }
+ ScriptValue() { }
ScriptValue(JSC::JSGlobalData& globalData, JSC::JSValue value) : m_value(globalData, value) {}
virtual ~ScriptValue() {}
JSC::JSValue jsValue() const { return m_value.get(); }
bool getString(ScriptState*, String& result) const;
- String toString(ScriptState* scriptState) const { return ustringToString(m_value.get().toString(scriptState)); }
+ String toString(ScriptState*) const;
bool isEqual(ScriptState*, const ScriptValue&) const;
bool isNull() const;
bool isUndefined() const;
bool isObject() const;
bool isFunction() const;
- bool hasNoValue() const { return m_value.isEmpty(); }
+ bool hasNoValue() const { return !m_value; }
bool operator==(const ScriptValue& other) const { return m_value == other.m_value; }
- PassRefPtr<SerializedScriptValue> serialize(ScriptState*);
- static ScriptValue deserialize(ScriptState*, SerializedScriptValue*);
+ PassRefPtr<SerializedScriptValue> serialize(ScriptState*, SerializationErrorMode = Throwing);
+ static ScriptValue deserialize(ScriptState*, SerializedScriptValue*, SerializationErrorMode = Throwing);
static ScriptValue undefined();
@@ -71,7 +72,7 @@ public:
#endif
private:
- JSC::Global<JSC::Unknown> m_value;
+ JSC::Strong<JSC::Unknown> m_value;
};
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/ScriptWrappable.h b/Source/WebCore/bindings/js/ScriptWrappable.h
index 0fbe9e4..4fef506 100644
--- a/Source/WebCore/bindings/js/ScriptWrappable.h
+++ b/Source/WebCore/bindings/js/ScriptWrappable.h
@@ -32,28 +32,29 @@
#define ScriptWrappable_h
#include "JSDOMWrapper.h"
-#include <runtime/WeakGCPtr.h>
+#include <heap/Weak.h>
namespace WebCore {
class ScriptWrappable {
public:
- ScriptWrappable()
+ JSDOMWrapper* wrapper() const
{
+ return m_wrapper.get();
}
- DOMObject* wrapper() const
+ void setWrapper(JSC::JSGlobalData& globalData, JSDOMWrapper* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context)
{
- return m_wrapper.get();
+ m_wrapper.set(globalData, wrapper, wrapperOwner, context);
}
- void setWrapper(JSC::JSGlobalData& globalData, DOMObject* wrapper)
+ void clearWrapper()
{
- m_wrapper.set(globalData, wrapper, 0);
+ m_wrapper.clear();
}
private:
- JSC::WeakGCPtr<DOMObject> m_wrapper;
+ JSC::Weak<JSDOMWrapper> m_wrapper;
};
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.cpp b/Source/WebCore/bindings/js/SerializedScriptValue.cpp
index a9c1b24..bbe0ca4 100644
--- a/Source/WebCore/bindings/js/SerializedScriptValue.cpp
+++ b/Source/WebCore/bindings/js/SerializedScriptValue.cpp
@@ -36,6 +36,7 @@
#include "JSFile.h"
#include "JSFileList.h"
#include "JSImageData.h"
+#include "JSNavigator.h"
#include "SharedBuffer.h"
#include <limits>
#include <JavaScriptCore/APICast.h>
@@ -160,6 +161,8 @@ static const unsigned int StringPoolTag = 0xFFFFFFFE;
* RegExpTag <pattern:StringData><flags:StringData>
*/
+typedef pair<JSC::JSValue, SerializationReturnCode> DeserializationResult;
+
class CloneBase {
protected:
CloneBase(ExecState* exec)
@@ -247,7 +250,7 @@ template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, con
class CloneSerializer : CloneBase {
public:
- static bool serialize(ExecState* exec, JSValue value, Vector<uint8_t>& out)
+ static SerializationReturnCode serialize(ExecState* exec, JSValue value, Vector<uint8_t>& out)
{
CloneSerializer serializer(exec, out);
return serializer.serialize(value);
@@ -274,7 +277,7 @@ private:
write(CurrentVersion);
}
- bool serialize(JSValue in);
+ SerializationReturnCode serialize(JSValue in);
bool isArray(JSValue value)
{
@@ -414,6 +417,13 @@ private:
if (isArray(value))
return false;
+
+ // Object cannot be serialized because the act of walking the object creates new objects
+ if (value.isObject() && asObject(value)->inherits(&JSNavigator::s_info)) {
+ fail();
+ write(NullTag);
+ return true;
+ }
if (value.isObject()) {
JSObject* obj = asObject(value);
@@ -598,7 +608,7 @@ private:
Identifier m_emptyIdentifier;
};
-bool CloneSerializer::serialize(JSValue in)
+SerializationReturnCode CloneSerializer::serialize(JSValue in)
{
Vector<uint32_t, 16> indexStack;
Vector<uint32_t, 16> lengthStack;
@@ -614,10 +624,8 @@ bool CloneSerializer::serialize(JSValue in)
arrayStartState:
case ArrayStartState: {
ASSERT(isArray(inValue));
- if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) {
- throwStackOverflow();
- return false;
- }
+ if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion)
+ return StackOverflowError;
JSArray* inArray = asArray(inValue);
unsigned length = inArray->length();
@@ -631,10 +639,8 @@ bool CloneSerializer::serialize(JSValue in)
arrayStartVisitMember:
case ArrayStartVisitMember: {
if (!--tickCount) {
- if (didTimeOut()) {
- throwInterruptedException();
- return false;
- }
+ if (didTimeOut())
+ return InterruptedExecutionError;
tickCount = ticksUntilNextCheck();
}
@@ -673,10 +679,8 @@ bool CloneSerializer::serialize(JSValue in)
objectStartState:
case ObjectStartState: {
ASSERT(inValue.isObject());
- if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) {
- throwStackOverflow();
- return false;
- }
+ if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion)
+ return StackOverflowError;
JSObject* inObject = asObject(inValue);
if (!startObject(inObject))
break;
@@ -689,10 +693,8 @@ bool CloneSerializer::serialize(JSValue in)
objectStartVisitMember:
case ObjectStartVisitMember: {
if (!--tickCount) {
- if (didTimeOut()) {
- throwInterruptedException();
- return false;
- }
+ if (didTimeOut())
+ return InterruptedExecutionError;
tickCount = ticksUntilNextCheck();
}
@@ -708,7 +710,7 @@ bool CloneSerializer::serialize(JSValue in)
}
inValue = getProperty(object, properties[index]);
if (shouldTerminate())
- return false;
+ return ExistingExceptionError;
if (!inValue) {
// Property was removed during serialisation
@@ -718,7 +720,7 @@ bool CloneSerializer::serialize(JSValue in)
write(properties[index]);
if (shouldTerminate())
- return false;
+ return ExistingExceptionError;
if (!dumpIfTerminal(inValue)) {
stateStack.append(ObjectEndVisitMember);
@@ -728,7 +730,7 @@ bool CloneSerializer::serialize(JSValue in)
}
case ObjectEndVisitMember: {
if (shouldTerminate())
- return false;
+ return ExistingExceptionError;
indexStack.last()++;
goto objectStartVisitMember;
@@ -749,17 +751,15 @@ bool CloneSerializer::serialize(JSValue in)
stateStack.removeLast();
if (!--tickCount) {
- if (didTimeOut()) {
- throwInterruptedException();
- return false;
- }
+ if (didTimeOut())
+ return InterruptedExecutionError;
tickCount = ticksUntilNextCheck();
}
}
if (m_failed)
- return false;
+ return UnspecifiedError;
- return true;
+ return SuccessfullyCompleted;
}
class CloneDeserializer : CloneBase {
@@ -783,15 +783,13 @@ public:
return String(str.impl());
}
- static JSValue deserialize(ExecState* exec, JSGlobalObject* globalObject, const Vector<uint8_t>& buffer)
+ static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject, const Vector<uint8_t>& buffer)
{
if (!buffer.size())
- return jsNull();
+ return make_pair(jsNull(), UnspecifiedError);
CloneDeserializer deserializer(exec, globalObject, buffer);
- if (!deserializer.isValid()) {
- deserializer.throwValidationError();
- return JSValue();
- }
+ if (!deserializer.isValid())
+ return make_pair(JSValue(), ValidationError);
return deserializer.deserialize();
}
@@ -846,7 +844,7 @@ private:
m_version = 0xFFFFFFFF;
}
- JSValue deserialize();
+ DeserializationResult deserialize();
void throwValidationError()
{
@@ -1193,7 +1191,7 @@ private:
Vector<CachedString> m_constantPool;
};
-JSValue CloneDeserializer::deserialize()
+DeserializationResult CloneDeserializer::deserialize()
{
Vector<uint32_t, 16> indexStack;
Vector<Identifier, 16> propertyNameStack;
@@ -1222,10 +1220,8 @@ JSValue CloneDeserializer::deserialize()
arrayStartVisitMember:
case ArrayStartVisitMember: {
if (!--tickCount) {
- if (didTimeOut()) {
- throwInterruptedException();
- return JSValue();
- }
+ if (didTimeOut())
+ return make_pair(JSValue(), InterruptedExecutionError);
tickCount = ticksUntilNextCheck();
}
@@ -1259,10 +1255,8 @@ JSValue CloneDeserializer::deserialize()
}
objectStartState:
case ObjectStartState: {
- if (outputObjectStack.size() + outputArrayStack.size() > maximumFilterRecursion) {
- throwStackOverflow();
- return JSValue();
- }
+ if (outputObjectStack.size() + outputArrayStack.size() > maximumFilterRecursion)
+ return make_pair(JSValue(), StackOverflowError);
JSObject* outObject = constructEmptyObject(m_exec, m_globalObject);
m_gcBuffer.append(outObject);
outputObjectStack.append(outObject);
@@ -1271,10 +1265,8 @@ JSValue CloneDeserializer::deserialize()
objectStartVisitMember:
case ObjectStartVisitMember: {
if (!--tickCount) {
- if (didTimeOut()) {
- throwInterruptedException();
- return JSValue();
- }
+ if (didTimeOut())
+ return make_pair(JSValue(), InterruptedExecutionError);
tickCount = ticksUntilNextCheck();
}
@@ -1322,20 +1314,17 @@ JSValue CloneDeserializer::deserialize()
stateStack.removeLast();
if (!--tickCount) {
- if (didTimeOut()) {
- throwInterruptedException();
- return JSValue();
- }
+ if (didTimeOut())
+ return make_pair(JSValue(), InterruptedExecutionError);
tickCount = ticksUntilNextCheck();
}
}
ASSERT(outValue);
ASSERT(!m_failed);
- return outValue;
+ return make_pair(outValue, SuccessfullyCompleted);
error:
fail();
- throwValidationError();
- return JSValue();
+ return make_pair(JSValue(), ValidationError);
}
@@ -1349,11 +1338,16 @@ SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer)
m_data.swap(buffer);
}
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value)
+PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value, SerializationErrorMode throwExceptions)
{
Vector<uint8_t> buffer;
- if (!CloneSerializer::serialize(exec, value, buffer))
+ SerializationReturnCode code = CloneSerializer::serialize(exec, value, buffer);
+ if (throwExceptions == Throwing)
+ maybeThrowExceptionIfSerializationFailed(exec, code);
+
+ if (!serializationDidCompleteSuccessfully(code))
return 0;
+
return adoptRef(new SerializedScriptValue(buffer));
}
@@ -1392,9 +1386,12 @@ String SerializedScriptValue::toString()
return CloneDeserializer::deserializeString(m_data);
}
-JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject)
+JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject, SerializationErrorMode throwExceptions)
{
- return CloneDeserializer::deserialize(exec, globalObject, m_data);
+ DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, m_data);
+ if (throwExceptions == Throwing)
+ maybeThrowExceptionIfSerializationFailed(exec, result.second);
+ return result.first;
}
JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception)
@@ -1418,4 +1415,33 @@ SerializedScriptValue* SerializedScriptValue::nullValue()
return emptyValue.get();
}
+void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code)
+{
+ if (code == SuccessfullyCompleted)
+ return;
+
+ switch (code) {
+ case StackOverflowError:
+ throwError(exec, createStackOverflowError(exec));
+ break;
+ case InterruptedExecutionError:
+ throwError(exec, createInterruptedExecutionException(&exec->globalData()));
+ break;
+ case ValidationError:
+ throwError(exec, createTypeError(exec, "Unable to deserialize data."));
+ break;
+ case ExistingExceptionError:
+ break;
+ case UnspecifiedError:
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code)
+{
+ return (code == SuccessfullyCompleted);
+}
+
}
diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.h b/Source/WebCore/bindings/js/SerializedScriptValue.h
index 94bc477..0e7fed0 100644
--- a/Source/WebCore/bindings/js/SerializedScriptValue.h
+++ b/Source/WebCore/bindings/js/SerializedScriptValue.h
@@ -27,19 +27,34 @@
#ifndef SerializedScriptValue_h
#define SerializedScriptValue_h
-#include "ScriptValue.h"
+#include <heap/Strong.h>
+#include <runtime/JSValue.h>
#include <wtf/Forward.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
typedef const struct OpaqueJSContext* JSContextRef;
typedef const struct OpaqueJSValue* JSValueRef;
namespace WebCore {
+
+enum SerializationReturnCode {
+ SuccessfullyCompleted,
+ StackOverflowError,
+ InterruptedExecutionError,
+ ValidationError,
+ ExistingExceptionError,
+ UnspecifiedError
+};
+
+enum SerializationErrorMode { NonThrowing, Throwing };
+
class SharedBuffer;
class SerializedScriptValue : public RefCounted<SerializedScriptValue> {
public:
- static PassRefPtr<SerializedScriptValue> create(JSC::ExecState* exec, JSC::JSValue value);
+ static PassRefPtr<SerializedScriptValue> create(JSC::ExecState*, JSC::JSValue, SerializationErrorMode = Throwing);
static PassRefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef value, JSValueRef* exception);
static PassRefPtr<SerializedScriptValue> create(String string);
static PassRefPtr<SerializedScriptValue> adopt(Vector<uint8_t>& buffer)
@@ -50,14 +65,19 @@ public:
static PassRefPtr<SerializedScriptValue> create();
static SerializedScriptValue* nullValue();
- JSC::JSValue deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject);
String toString();
+
+ JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*, SerializationErrorMode = Throwing);
JSValueRef deserialize(JSContextRef, JSValueRef* exception);
+
const Vector<uint8_t>& data() { return m_data; }
~SerializedScriptValue();
private:
+ static void maybeThrowExceptionIfSerializationFailed(JSC::ExecState*, SerializationReturnCode);
+ static bool serializationDidCompleteSuccessfully(SerializationReturnCode);
+
SerializedScriptValue(Vector<unsigned char>&);
Vector<unsigned char> m_data;
};
diff --git a/Source/WebCore/bindings/js/WorkerScriptController.cpp b/Source/WebCore/bindings/js/WorkerScriptController.cpp
index 67b0441..1f29dfc 100644
--- a/Source/WebCore/bindings/js/WorkerScriptController.cpp
+++ b/Source/WebCore/bindings/js/WorkerScriptController.cpp
@@ -61,6 +61,7 @@ WorkerScriptController::WorkerScriptController(WorkerContext* workerContext)
WorkerScriptController::~WorkerScriptController()
{
m_workerContextWrapper.clear(); // Unprotect the global object.
+ m_globalData->clearBuiltinStructures();
m_globalData->heap.destroy();
}
@@ -73,25 +74,25 @@ void WorkerScriptController::initScript()
// Explicitly protect the global object's prototype so it isn't collected
// when we allocate the global object. (Once the global object is fully
// constructed, it can mark its own prototype.)
- RefPtr<Structure> workerContextPrototypeStructure = JSWorkerContextPrototype::createStructure(*m_globalData, jsNull());
- Global<JSWorkerContextPrototype> workerContextPrototype(*m_globalData, new (m_globalData.get()) JSWorkerContextPrototype(0, workerContextPrototypeStructure.release()));
+ Structure* workerContextPrototypeStructure = JSWorkerContextPrototype::createStructure(*m_globalData, jsNull());
+ Strong<JSWorkerContextPrototype> workerContextPrototype(*m_globalData, new (m_globalData.get()) JSWorkerContextPrototype(*m_globalData, 0, workerContextPrototypeStructure));
if (m_workerContext->isDedicatedWorkerContext()) {
- RefPtr<Structure> dedicatedContextPrototypeStructure = JSDedicatedWorkerContextPrototype::createStructure(*m_globalData, workerContextPrototype.get());
- Global<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype(*m_globalData, new (m_globalData.get()) JSDedicatedWorkerContextPrototype(0, dedicatedContextPrototypeStructure.release()));
- RefPtr<Structure> structure = JSDedicatedWorkerContext::createStructure(*m_globalData, dedicatedContextPrototype.get());
+ Structure* dedicatedContextPrototypeStructure = JSDedicatedWorkerContextPrototype::createStructure(*m_globalData, workerContextPrototype.get());
+ Strong<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype(*m_globalData, new (m_globalData.get()) JSDedicatedWorkerContextPrototype(*m_globalData, 0, dedicatedContextPrototypeStructure));
+ Structure* structure = JSDedicatedWorkerContext::createStructure(*m_globalData, dedicatedContextPrototype.get());
- m_workerContextWrapper.set(*m_globalData, new (m_globalData.get()) JSDedicatedWorkerContext(structure.release(), m_workerContext->toDedicatedWorkerContext()));
+ m_workerContextWrapper.set(*m_globalData, new (m_globalData.get()) JSDedicatedWorkerContext(*m_globalData, structure, m_workerContext->toDedicatedWorkerContext()));
workerContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get());
dedicatedContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get());
#if ENABLE(SHARED_WORKERS)
} else {
ASSERT(m_workerContext->isSharedWorkerContext());
- RefPtr<Structure> sharedContextPrototypeStructure = JSSharedWorkerContextPrototype::createStructure(*m_globalData, workerContextPrototype.get());
- Global<JSSharedWorkerContextPrototype> sharedContextPrototype(*m_globalData, new (m_globalData.get()) JSSharedWorkerContextPrototype(0, sharedContextPrototypeStructure.release()));
- RefPtr<Structure> structure = JSSharedWorkerContext::createStructure(*m_globalData, sharedContextPrototype.get());
+ Structure* sharedContextPrototypeStructure = JSSharedWorkerContextPrototype::createStructure(*m_globalData, workerContextPrototype.get());
+ Strong<JSSharedWorkerContextPrototype> sharedContextPrototype(*m_globalData, new (m_globalData.get()) JSSharedWorkerContextPrototype(*m_globalData, 0, sharedContextPrototypeStructure));
+ Structure* structure = JSSharedWorkerContext::createStructure(*m_globalData, sharedContextPrototype.get());
- m_workerContextWrapper.set(*m_globalData, new (m_globalData.get()) JSSharedWorkerContext(structure.release(), m_workerContext->toSharedWorkerContext()));
+ m_workerContextWrapper.set(*m_globalData, new (m_globalData.get()) JSSharedWorkerContext(*m_globalData, structure, m_workerContext->toSharedWorkerContext()));
workerContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get());
sharedContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get());
#endif
@@ -100,11 +101,9 @@ void WorkerScriptController::initScript()
ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode)
{
- {
- MutexLocker lock(m_sharedDataMutex);
- if (m_executionForbidden)
- return ScriptValue();
- }
+ if (isExecutionForbidden())
+ return ScriptValue();
+
ScriptValue exception;
ScriptValue result(evaluate(sourceCode, &exception));
if (exception.jsValue()) {
@@ -116,11 +115,8 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode)
ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* exception)
{
- {
- MutexLocker lock(m_sharedDataMutex);
- if (m_executionForbidden)
- return ScriptValue();
- }
+ if (isExecutionForbidden())
+ return ScriptValue();
initScriptIfNeeded();
JSLock lock(SilenceAssertionsOnly);
@@ -130,10 +126,18 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode,
Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), sourceCode.jsSourceCode(), m_workerContextWrapper.get());
m_workerContextWrapper->globalData().timeoutChecker.stop();
- if (comp.complType() == Normal || comp.complType() == ReturnValue)
+
+ ComplType completionType = comp.complType();
+
+ if (completionType == Terminated || m_workerContextWrapper->globalData().terminator.shouldTerminate()) {
+ forbidExecution();
+ return ScriptValue();
+ }
+
+ if (completionType == Normal || completionType == ReturnValue)
return ScriptValue(*m_globalData, comp.value());
- if (comp.complType() == Throw) {
+ if (completionType == Throw) {
String errorMessage;
int lineNumber = 0;
String sourceURL = sourceCode.url().string();
@@ -150,16 +154,21 @@ void WorkerScriptController::setException(ScriptValue exception)
throwError(m_workerContextWrapper->globalExec(), exception.jsValue());
}
-void WorkerScriptController::forbidExecution(ForbidExecutionOption option)
+void WorkerScriptController::scheduleExecutionTermination()
{
- // This function may be called from another thread.
- // Mutex protection for m_executionForbidden is needed to guarantee that the value is synchronized between processors, because
- // if it were not, the worker could re-enter JSC::evaluate(), but with timeout already reset.
- // It is not critical for Terminator::m_shouldTerminate to be synchronized, we just rely on it reaching the worker thread's processor sooner or later.
- MutexLocker lock(m_sharedDataMutex);
+ m_globalData->terminator.terminateSoon();
+}
+
+void WorkerScriptController::forbidExecution()
+{
+ ASSERT(m_workerContext->isContextThread());
m_executionForbidden = true;
- if (option == TerminateRunningScript)
- m_globalData->terminator.terminateSoon();
+}
+
+bool WorkerScriptController::isExecutionForbidden() const
+{
+ ASSERT(m_workerContext->isContextThread());
+ return m_executionForbidden;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/WorkerScriptController.h b/Source/WebCore/bindings/js/WorkerScriptController.h
index c3b8215..0e52988 100644
--- a/Source/WebCore/bindings/js/WorkerScriptController.h
+++ b/Source/WebCore/bindings/js/WorkerScriptController.h
@@ -29,7 +29,7 @@
#if ENABLE(WORKERS)
-#include <collector/handles/Global.h>
+#include <heap/Strong.h>
#include <wtf/Forward.h>
#include <wtf/Threading.h>
@@ -61,9 +61,17 @@ namespace WebCore {
void setException(ScriptValue);
- enum ForbidExecutionOption { TerminateRunningScript, LetRunningScriptFinish };
- void forbidExecution(ForbidExecutionOption);
- bool isExecutionForbidden() const { return m_executionForbidden; }
+ // Async request to terminate a JS run execution. Eventually causes termination
+ // exception raised during JS execution, if the worker thread happens to run JS.
+ // After JS execution was terminated in this way, the Worker thread has to use
+ // forbidExecution()/isExecutionForbidden() to guard against reentry into JS.
+ // Can be called from any thread.
+ void scheduleExecutionTermination();
+
+ // Called on Worker thread when JS exits with termination exception caused by forbidExecution() request,
+ // or by Worker thread termination code to prevent future entry into JS.
+ void forbidExecution();
+ bool isExecutionForbidden() const;
JSC::JSGlobalData* globalData() { return m_globalData.get(); }
@@ -77,9 +85,7 @@ namespace WebCore {
RefPtr<JSC::JSGlobalData> m_globalData;
WorkerContext* m_workerContext;
- JSC::Global<JSWorkerContext> m_workerContextWrapper;
-
- Mutex m_sharedDataMutex;
+ JSC::Strong<JSWorkerContext> m_workerContextWrapper;
bool m_executionForbidden;
};
diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
index 12b477b..181fd24 100644
--- a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
+++ b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -200,7 +200,7 @@ sub GetParentClassName
my $dataNode = shift;
return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"};
- return "DOMObjectWithGlobalPointer" if (@{$dataNode->parents} eq 0);
+ return "JSDOMWrapperWithGlobalPointer" if (@{$dataNode->parents} eq 0);
return "JS" . $codeGenerator->StripModule($dataNode->parents(0));
}
@@ -682,11 +682,11 @@ sub GenerateHeader
# Constructor
if ($interfaceName eq "DOMWindow") {
- push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
+ push(@headerContent, " $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
} elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
- push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n");
+ push(@headerContent, " $className(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<$implType>);\n");
} else {
- push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
+ push(@headerContent, " $className(JSC::Structure*, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
}
# Prototype
@@ -746,7 +746,7 @@ sub GenerateHeader
$structureFlags{"JSC::NeedsThisConversion"} = 1;
}
push(@headerContent,
- " static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" .
+ " static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" .
" {\n" .
" return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" .
" }\n\n");
@@ -923,7 +923,7 @@ sub GenerateHeader
}
if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
if ($interfaceName eq "NodeFilter") {
- push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSValue);\n");
+ push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSGlobalData&, JSC::JSValue);\n");
} else {
push(@headerContent, "$implType* to${interfaceName}(JSC::JSValue);\n");
}
@@ -958,7 +958,7 @@ sub GenerateHeader
$structureFlags{"JSC::OverridesMarkChildren"} = 1;
}
push(@headerContent,
- " static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" .
+ " static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" .
" {\n" .
" return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" .
" }\n");
@@ -970,7 +970,7 @@ sub GenerateHeader
# Custom defineGetter function
push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};
- push(@headerContent, " ${className}Prototype(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObjectWithGlobalObject(globalObject, structure) { }\n");
+ push(@headerContent, " ${className}Prototype(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) : JSC::JSObjectWithGlobalObject(globalData, globalObject, structure) { }\n");
# structure flags
push(@headerContent, "protected:\n");
@@ -1304,7 +1304,7 @@ sub GenerateImplementation
push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n");
push(@implContent, "{\n");
push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n");
- push(@implContent, "}\n");
+ push(@implContent, "}\n\n");
push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSObjectWithGlobalObject::s_info, 0, get${className}PrototypeTable };\n\n");
} else {
push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSObjectWithGlobalObject::s_info, &${className}PrototypeTable, 0 };\n\n");
@@ -1379,7 +1379,7 @@ sub GenerateImplementation
push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n");
push(@implContent, "{\n");
push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n");
- push(@implContent, "}\n");
+ push(@implContent, "}\n\n");
}
push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", &" . $parentClassName . "::s_info, ");
@@ -1407,14 +1407,14 @@ sub GenerateImplementation
# Constructor
if ($interfaceName eq "DOMWindow") {
AddIncludesForType("JSDOMWindowShell");
- push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
- push(@implContent, " : $parentClassName(structure, impl, shell)\n");
+ push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
+ push(@implContent, " : $parentClassName(globalData, structure, impl, shell)\n");
} elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
AddIncludesForType($interfaceName);
- push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n");
- push(@implContent, " : $parentClassName(structure, impl)\n");
+ push(@implContent, "${className}::$className(JSGlobalData& globalData, Structure* structure, PassRefPtr<$implType> impl)\n");
+ push(@implContent, " : $parentClassName(globalData, structure, impl)\n");
} else {
- push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
+ push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
if ($hasParent) {
push(@implContent, " : $parentClassName(structure, globalObject, impl)\n");
} else {
@@ -1442,9 +1442,9 @@ sub GenerateImplementation
push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n");
push(@implContent, "{\n");
if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
- push(@implContent, " return new (exec) ${className}Prototype(globalObject, ${className}Prototype::createStructure(exec->globalData(), ${parentClassName}Prototype::self(exec, globalObject)));\n");
+ push(@implContent, " return new (exec) ${className}Prototype(exec->globalData(), globalObject, ${className}Prototype::createStructure(exec->globalData(), ${parentClassName}Prototype::self(exec, globalObject)));\n");
} else {
- push(@implContent, " return new (exec) ${className}Prototype(globalObject, ${className}Prototype::createStructure(globalObject->globalData(), globalObject->objectPrototype()));\n");
+ push(@implContent, " return new (exec) ${className}Prototype(exec->globalData(), globalObject, ${className}Prototype::createStructure(globalObject->globalData(), globalObject->objectPrototype()));\n");
}
push(@implContent, "}\n\n");
}
@@ -1540,7 +1540,7 @@ sub GenerateImplementation
my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
$constructorType =~ s/Constructor$//;
# Constructor attribute is only used by DOMWindow.idl, so it's correct to pass castedThis as the global object
- # Once DOMObjects have a back-pointer to the globalObject we can pass castedThis->globalObject()
+ # Once JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject()
push(@implContent, " return JS" . $constructorType . "::getConstructor(exec, castedThis);\n");
} elsif (!@{$attribute->getterExceptions}) {
push(@implContent, " UNUSED_PARAM(exec);\n");
@@ -1590,7 +1590,7 @@ sub GenerateImplementation
push(@implContent, " return result;\n");
}
- push(@implContent, "}\n");
+ push(@implContent, "}\n\n");
push(@implContent, "#endif\n") if $attributeConditionalString;
@@ -1610,8 +1610,7 @@ sub GenerateImplementation
}
push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n");
- push(@implContent, "}\n");
- push(@implContent, "\n");
+ push(@implContent, "}\n\n");
}
}
@@ -1769,7 +1768,7 @@ sub GenerateImplementation
}
}
- push(@implContent, "}\n");
+ push(@implContent, "}\n\n");
push(@implContent, "#endif\n") if $attributeConditionalString;
@@ -1799,8 +1798,7 @@ sub GenerateImplementation
} else {
push(@implContent, " static_cast<$className*>(thisObject)->putDirect(exec->globalData(), Identifier(exec, \"$name\"), value);\n");
}
- push(@implContent, "}\n");
- push(@implContent, "\n");
+ push(@implContent, "}\n\n");
}
}
}
@@ -2095,7 +2093,7 @@ sub GenerateImplementation
} else {
push(@implContent, " return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(index));\n");
}
- push(@implContent, "}\n");
+ push(@implContent, "}\n\n");
if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
$implIncludes{"JSNode.h"} = 1;
$implIncludes{"Node.h"} = 1;
@@ -2106,7 +2104,7 @@ sub GenerateImplementation
push(@implContent, "\nJSValue ${className}::getByIndex(ExecState*, unsigned index)\n");
push(@implContent, "{\n");
push(@implContent, " return jsNumber(static_cast<$implClassName*>(impl())->item(index));\n");
- push(@implContent, "}\n");
+ push(@implContent, "}\n\n");
if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
$implIncludes{"JSNode.h"} = 1;
$implIncludes{"Node.h"} = 1;
@@ -2115,17 +2113,17 @@ sub GenerateImplementation
if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) {
if ($svgPropertyType) {
- push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n");
+ push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n");
} else {
- push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n");
+ push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n");
}
push(@implContent, "{\n");
if ($svgPropertyType) {
- push(@implContent, " return getDOMObjectWrapper<$className, $implType>(exec, globalObject, object);\n");
+ push(@implContent, " return wrap<$className, $implType>(exec, globalObject, impl);\n");
} else {
- push(@implContent, " return getDOMObjectWrapper<$className>(exec, globalObject, object);\n");
+ push(@implContent, " return wrap<$className>(exec, globalObject, impl);\n");
}
- push(@implContent, "}\n");
+ push(@implContent, "}\n\n");
}
if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {
@@ -2466,6 +2464,11 @@ sub JSValueToNative
return "exec->globalData(), $value";
}
+ if ($type eq "NodeFilter") {
+ $implIncludes{"JS$type.h"} = 1;
+ return "to$type(exec->globalData(), $value)";
+ }
+
if ($type eq "MediaQueryListListener") {
$implIncludes{"MediaQueryListListener.h"} = 1;
return "MediaQueryListListener::create(ScriptValue(exec->globalData(), " . $value ."))";
@@ -2514,7 +2517,6 @@ sub NativeToJSValue
}
if ($codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp") {
- $implIncludes{"<runtime/JSNumberCell.h>"} = 1;
return "jsNumber($value)";
}
@@ -2873,7 +2875,7 @@ sub GenerateConstructorDeclaration
push(@$outputArray, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");
push(@$outputArray, " static const JSC::ClassInfo s_info;\n");
- push(@$outputArray, " static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n");
+ push(@$outputArray, " static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n");
push(@$outputArray, " {\n");
push(@$outputArray, " return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n");
push(@$outputArray, " }\n");
@@ -2920,12 +2922,12 @@ sub GenerateConstructorDefinition
push(@$outputArray, "bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
push(@$outputArray, "{\n");
- push(@$outputArray, " return getStaticValueSlot<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, slot);\n");
+ push(@$outputArray, " return getStaticValueSlot<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, slot);\n");
push(@$outputArray, "}\n\n");
push(@$outputArray, "bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
push(@$outputArray, "{\n");
- push(@$outputArray, " return getStaticValueDescriptor<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, descriptor);\n");
+ push(@$outputArray, " return getStaticValueDescriptor<${constructorClassName}, JSDOMWrapper>(exec, &${constructorClassName}Table, this, propertyName, descriptor);\n");
push(@$outputArray, "}\n\n");
if ($canConstruct) {
diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm b/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm
index 6fc0b9a..22051bf 100644
--- a/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm
+++ b/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm
@@ -448,9 +448,7 @@ sub GetInternalFields
push(@customInternalFields, "eventListenerCacheIndex");
}
- if (IsSubType($dataNode, "Document")) {
- push(@customInternalFields, "implementationIndex");
- } elsif ($name eq "DOMWindow") {
+ if ($name eq "DOMWindow") {
push(@customInternalFields, "enteredIsolatedWorldIndex");
}
return @customInternalFields;
@@ -2348,6 +2346,7 @@ sub GenerateCallbackImplementation
push(@implFixedHeader, GenerateImplementationContentHeader($dataNode));
$implIncludes{"ScriptExecutionContext.h"} = 1;
+ $implIncludes{"V8Binding.h"} = 1;
$implIncludes{"V8CustomVoidCallback.h"} = 1;
$implIncludes{"V8Proxy.h"} = 1;
@@ -2553,6 +2552,7 @@ sub HasCustomToV8Implementation {
return 0 if $interfaceName eq "AbstractWorker";
return 0 if $interfaceName eq "CanvasRenderingContext";
return 0 if $interfaceName eq "SVGElementInstance";
+ return 0 if $interfaceName eq "NodeList";
# For everything else, do what JSC does.
return $dataNode->extendedAttributes->{"CustomToJS"};
diff --git a/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp b/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp
index c17f73d..b0a4f69 100644
--- a/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp
+++ b/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp
@@ -24,6 +24,7 @@
#if ENABLE(DATABASE)
#include "ScriptExecutionContext.h"
+#include "V8Binding.h"
#include "V8Class1.h"
#include "V8Class2.h"
#include "V8CustomVoidCallback.h"
diff --git a/Source/WebCore/bindings/v8/DebuggerScript.js b/Source/WebCore/bindings/v8/DebuggerScript.js
index fe6e8ab..c6540d7 100644
--- a/Source/WebCore/bindings/v8/DebuggerScript.js
+++ b/Source/WebCore/bindings/v8/DebuggerScript.js
@@ -38,11 +38,6 @@ DebuggerScript.PauseOnExceptionsState = {
PauseOnUncaughtExceptions: 2
};
-DebuggerScript.ScriptWorldType = {
- MainWorld : 0,
- ExtensionsWorld : 1
-};
-
DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions;
Debug.clearBreakOnException();
Debug.clearBreakOnUncaughtException();
@@ -52,6 +47,21 @@ DebuggerScript.getAfterCompileScript = function(eventData)
return DebuggerScript._formatScript(eventData.script_.script_);
}
+DebuggerScript.getWorkerScripts = function()
+{
+ var result = [];
+ var scripts = Debug.scripts();
+ for (var i = 0; i < scripts.length; ++i) {
+ var script = scripts[i];
+ // Workers don't share same V8 heap now so there is no need to complicate stuff with
+ // the context id like we do to discriminate between scripts from different pages.
+ // However we need to filter out v8 native scripts.
+ if (script.context_data && script.context_data === "worker")
+ result.push(DebuggerScript._formatScript(script));
+ }
+ return result;
+}
+
DebuggerScript.getScripts = function(contextData)
{
var result = [];
@@ -76,24 +86,19 @@ DebuggerScript.getScripts = function(contextData)
DebuggerScript._formatScript = function(script)
{
- var scriptWorldType = DebuggerScript.ScriptWorldType.MainWorld;
- if (script.context_data && script.context_data.indexOf("injected") == 0)
- scriptWorldType = DebuggerScript.ScriptWorldType.ExtensionsWorld;
return {
id: script.id,
name: script.nameOrSourceURL(),
source: script.source,
lineOffset: script.line_offset,
columnOffset: script.column_offset,
- scriptWorldType: scriptWorldType
+ isContentScript: !!script.context_data && script.context_data.indexOf("injected") == 0
};
}
DebuggerScript.setBreakpoint = function(execState, args)
{
- var breakId = Debug.setScriptBreakPointById(args.scriptId, args.lineNumber, args.columnNumber, args.condition);
- if (!args.enabled)
- Debug.disableScriptBreakPoint(breakId);
+ var breakId = Debug.setScriptBreakPointById(args.sourceID, args.lineNumber, args.columnNumber, args.condition);
var locations = Debug.findBreakPointActualLocations(breakId);
if (!locations.length)
@@ -252,7 +257,6 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame)
"line": location.line,
"column": location.column,
"functionName": functionName,
- "type": "function",
"thisObject": thisObject,
"scopeChain": scopeChain,
"scopeType": scopeType,
diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp
index 5758639..a0e14f3 100644
--- a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp
+++ b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp
@@ -67,11 +67,10 @@ String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBrea
v8::Context::Scope contextScope(debuggerContext);
v8::Local<v8::Object> args = v8::Object::New();
- args->Set(v8::String::New("scriptId"), v8String(sourceID));
+ args->Set(v8::String::New("sourceID"), v8String(sourceID));
args->Set(v8::String::New("lineNumber"), v8::Integer::New(scriptBreakpoint.lineNumber));
args->Set(v8::String::New("columnNumber"), v8::Integer::New(scriptBreakpoint.columnNumber));
args->Set(v8::String::New("condition"), v8String(scriptBreakpoint.condition));
- args->Set(v8::String::New("enabled"), v8::Boolean::New(scriptBreakpoint.enabled));
v8::Handle<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpoint")));
v8::Handle<v8::Value> breakpointId = v8::Debug::Call(setBreakpointFunction, args);
@@ -212,7 +211,7 @@ void ScriptDebugServer::stepOutOfFunction()
continueProgram();
}
-bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& newContent, String& newSourceOrErrorMessage)
+bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& newContent, String* error)
{
ensureDebuggerScriptCompiled();
v8::HandleScope scope;
@@ -230,11 +229,12 @@ bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& n
if (tryCatch.HasCaught()) {
v8::Local<v8::Message> message = tryCatch.Message();
if (!message.IsEmpty())
- newSourceOrErrorMessage = toWebCoreStringWithNullOrUndefinedCheck(message->Get());
+ *error = toWebCoreStringWithNullOrUndefinedCheck(message->Get());
+ else
+ *error = "Unknown error.";
return false;
}
ASSERT(!result.IsEmpty());
- newSourceOrErrorMessage = toWebCoreStringWithNullOrUndefinedCheck(result);
// Call stack may have changed after if the edited function was on the stack.
if (m_currentCallFrame)
@@ -351,7 +351,7 @@ void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8
toWebCoreStringWithNullOrUndefinedCheck(object->Get(v8::String::New("source"))),
object->Get(v8::String::New("lineOffset"))->ToInteger()->Value(),
object->Get(v8::String::New("columnOffset"))->ToInteger()->Value(),
- static_cast<ScriptWorldType>(object->Get(v8::String::New("scriptWorldType"))->Int32Value()));
+ object->Get(v8::String::New("isContentScript"))->ToBoolean()->Value());
}
void ScriptDebugServer::ensureDebuggerScriptCompiled()
diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.h b/Source/WebCore/bindings/v8/ScriptDebugServer.h
index 15004ea..93d897c 100644
--- a/Source/WebCore/bindings/v8/ScriptDebugServer.h
+++ b/Source/WebCore/bindings/v8/ScriptDebugServer.h
@@ -72,7 +72,7 @@ public:
void stepOverStatement();
void stepOutOfFunction();
- bool editScriptSource(const String& sourceID, const String& newContent, String& newSourceOrErrorMessage);
+ bool editScriptSource(const String& sourceID, const String& newContent, String* error);
void recompileAllJSFunctionsSoon() { }
void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) { }
diff --git a/Source/WebCore/bindings/v8/ScriptState.cpp b/Source/WebCore/bindings/v8/ScriptState.cpp
index fac1d26..600a92a 100644
--- a/Source/WebCore/bindings/v8/ScriptState.cpp
+++ b/Source/WebCore/bindings/v8/ScriptState.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2011 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
@@ -37,6 +37,10 @@
#include "ScriptController.h"
#include "V8HiddenPropertyName.h"
+#include "WorkerContext.h"
+#include "WorkerContextExecutionProxy.h"
+#include "WorkerScriptController.h"
+
#include <v8.h>
#include <wtf/Assertions.h>
@@ -111,4 +115,17 @@ ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page* page)
return mainWorldScriptState(page->mainFrame());
}
+#if ENABLE(WORKERS)
+ScriptState* scriptStateFromWorkerContext(WorkerContext* workerContext)
+{
+ WorkerContextExecutionProxy* proxy = workerContext->script()->proxy();
+ if (!proxy)
+ return 0;
+
+ v8::HandleScope handleScope;
+ v8::Local<v8::Context> context = proxy->context();
+ return ScriptState::forContext(context);
+}
+#endif
+
}
diff --git a/Source/WebCore/bindings/v8/ScriptState.h b/Source/WebCore/bindings/v8/ScriptState.h
index 0fecee8..c7dbbb2 100644
--- a/Source/WebCore/bindings/v8/ScriptState.h
+++ b/Source/WebCore/bindings/v8/ScriptState.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2011 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
@@ -41,6 +41,7 @@ class DOMWrapperWorld;
class Frame;
class Node;
class Page;
+class WorkerContext;
class ScriptState {
WTF_MAKE_NONCOPYABLE(ScriptState);
@@ -108,6 +109,10 @@ ScriptState* mainWorldScriptState(Frame*);
ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*);
ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*);
+#if ENABLE(WORKERS)
+ScriptState* scriptStateFromWorkerContext(WorkerContext*);
+#endif
+
inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); }
inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); }
diff --git a/Source/WebCore/bindings/v8/ScriptValue.cpp b/Source/WebCore/bindings/v8/ScriptValue.cpp
index ebe9ccc..3487d39 100644
--- a/Source/WebCore/bindings/v8/ScriptValue.cpp
+++ b/Source/WebCore/bindings/v8/ScriptValue.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2011 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
@@ -64,7 +64,12 @@ bool ScriptValue::getString(String& result) const
String ScriptValue::toString(ScriptState*) const
{
- return toWebCoreString(m_value);
+ v8::TryCatch block;
+ v8::Handle<v8::String> s = m_value->ToString();
+ // Handle the case where an exception is thrown as part of invoking toString on the object.
+ if (block.HasCaught())
+ return String();
+ return v8StringToWebCoreString<String>(s, DoNotExternalize);
}
#if ENABLE(INSPECTOR)
diff --git a/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp b/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp
index 6dc49fa..f1102c2 100644
--- a/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp
+++ b/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp
@@ -72,6 +72,10 @@ V8AbstractEventListener::~V8AbstractEventListener()
void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event* event)
{
+ // Don't reenter V8 if execution was terminated in this instance of V8.
+ if (context->isJSExecutionForbidden())
+ return;
+
ASSERT(event);
// The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it.
@@ -150,8 +154,12 @@ void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context
returnValue = callListenerFunction(context, jsEvent, event);
if (tryCatch.HasCaught())
event->target()->uncaughtExceptionInEventHandler();
- if (!tryCatch.CanContinue())
+
+ if (!tryCatch.CanContinue()) { // Result of TerminateExecution().
+ if (context->isWorkerContext())
+ static_cast<WorkerContext*>(context)->script()->forbidExecution();
return;
+ }
tryCatch.Reset();
// Restore the old event. This must be done for all exit paths through this method.
diff --git a/Source/WebCore/bindings/v8/V8DOMWrapper.cpp b/Source/WebCore/bindings/v8/V8DOMWrapper.cpp
index b439274..bef28a2 100644
--- a/Source/WebCore/bindings/v8/V8DOMWrapper.cpp
+++ b/Source/WebCore/bindings/v8/V8DOMWrapper.cpp
@@ -84,6 +84,7 @@
#endif
#if ENABLE(WEB_AUDIO)
+#include "V8AudioContext.h"
#include "V8JavaScriptAudioNode.h"
#endif
@@ -444,6 +445,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta
#if ENABLE(WEB_AUDIO)
if (JavaScriptAudioNode* jsAudioNode = target->toJavaScriptAudioNode())
return toV8(jsAudioNode);
+ if (AudioContext* audioContext = target->toAudioContext())
+ return toV8(audioContext);
#endif
ASSERT(0);
diff --git a/Source/WebCore/bindings/v8/V8GCController.cpp b/Source/WebCore/bindings/v8/V8GCController.cpp
index 82c9ca4..c9e9dfd 100644
--- a/Source/WebCore/bindings/v8/V8GCController.cpp
+++ b/Source/WebCore/bindings/v8/V8GCController.cpp
@@ -359,6 +359,24 @@ public:
GroupId groupId = calculateGroupId(cssStyleDeclaration);
m_grouper.append(GrouperItem(groupId, wrapper));
+ // Keep alive "dirty" primitive values (i.e. the ones that
+ // have user-added properties) by creating implicit
+ // references between the style declaration and the values
+ // in it.
+ if (cssStyleDeclaration->isMutableStyleDeclaration()) {
+ CSSMutableStyleDeclaration* cssMutableStyleDeclaration = static_cast<CSSMutableStyleDeclaration*>(cssStyleDeclaration);
+ Vector<v8::Persistent<v8::Value> > values;
+ values.reserveCapacity(cssMutableStyleDeclaration->length());
+ CSSMutableStyleDeclaration::const_iterator end = cssMutableStyleDeclaration->end();
+ for (CSSMutableStyleDeclaration::const_iterator it = cssMutableStyleDeclaration->begin(); it != end; ++it) {
+ v8::Persistent<v8::Object> value = store->domObjectMap().get(it->value());
+ if (!value.IsEmpty() && value->IsDirty())
+ values.append(value);
+ }
+ if (!values.isEmpty())
+ v8::V8::AddImplicitReferences(wrapper, values.data(), values.size());
+ }
+
} else if (typeInfo->isSubclass(&V8CSSRuleList::info)) {
CSSRuleList* cssRuleList = static_cast<CSSRuleList*>(object);
GroupId groupId(cssRuleList);
diff --git a/Source/WebCore/bindings/v8/V8Utilities.cpp b/Source/WebCore/bindings/v8/V8Utilities.cpp
index eebe6b5..b631359 100644
--- a/Source/WebCore/bindings/v8/V8Utilities.cpp
+++ b/Source/WebCore/bindings/v8/V8Utilities.cpp
@@ -127,4 +127,9 @@ ScriptExecutionContext* getScriptExecutionContext()
return 0;
}
+void throwTypeMismatchException()
+{
+ V8Proxy::throwError(V8Proxy::GeneralError, "TYPE_MISMATCH_ERR: DOM Exception 17");
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/V8Utilities.h b/Source/WebCore/bindings/v8/V8Utilities.h
index 1892bb7..4a44f3c 100644
--- a/Source/WebCore/bindings/v8/V8Utilities.h
+++ b/Source/WebCore/bindings/v8/V8Utilities.h
@@ -55,6 +55,36 @@ namespace WebCore {
ScriptExecutionContext* getScriptExecutionContext();
+ void throwTypeMismatchException();
+
+ enum CallbackAllowedValueFlag {
+ CallbackAllowUndefined = 1,
+ CallbackAllowNull = 1 << 1
+ };
+
+ typedef unsigned CallbackAllowedValueFlags;
+
+ // 'FunctionOnly' is assumed for the created callback.
+ template <typename V8CallbackType>
+ PassRefPtr<V8CallbackType> createFunctionOnlyCallback(v8::Local<v8::Value> value, bool& succeeded, CallbackAllowedValueFlags acceptedValues = 0)
+ {
+ succeeded = true;
+
+ if (value->IsUndefined() && (acceptedValues & CallbackAllowUndefined))
+ return 0;
+
+ if (value->IsNull() && (acceptedValues & CallbackAllowNull))
+ return 0;
+
+ if (!value->IsFunction()) {
+ succeeded = false;
+ throwTypeMismatchException();
+ return 0;
+ }
+
+ return V8CallbackType::create(value, getScriptExecutionContext());
+ }
+
class AllowAllocation {
public:
inline AllowAllocation()
diff --git a/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
index eb7252b..42259d5 100644
--- a/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
+++ b/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
@@ -150,6 +150,9 @@ bool WorkerContextExecutionProxy::initContextIfNeeded()
v8::Context::Scope scope(context);
+ // Set DebugId for the new context.
+ context->SetData(v8::String::New("worker"));
+
// Create a new JS object and use it as the prototype for the shadow global object.
WrapperTypeInfo* contextType = &V8DedicatedWorkerContext::info;
#if ENABLE(SHARED_WORKERS)
@@ -200,8 +203,10 @@ ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const St
v8::Handle<v8::Script> compiledScript = V8Proxy::compileScript(scriptString, fileName, scriptStartPosition);
v8::Local<v8::Value> result = runScript(compiledScript);
- if (!exceptionCatcher.CanContinue())
+ if (!exceptionCatcher.CanContinue()) {
+ m_workerContext->script()->forbidExecution();
return ScriptValue();
+ }
if (exceptionCatcher.HasCaught()) {
v8::Local<v8::Message> message = exceptionCatcher.Message();
diff --git a/Source/WebCore/bindings/v8/WorkerScriptController.cpp b/Source/WebCore/bindings/v8/WorkerScriptController.cpp
index 42e02e6..214da4e 100644
--- a/Source/WebCore/bindings/v8/WorkerScriptController.cpp
+++ b/Source/WebCore/bindings/v8/WorkerScriptController.cpp
@@ -68,11 +68,8 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode)
ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* exception)
{
- {
- MutexLocker lock(m_sharedDataMutex);
- if (m_executionForbidden)
- return ScriptValue();
- }
+ if (isExecutionForbidden())
+ return ScriptValue();
WorkerContextExecutionState state;
ScriptValue result = m_proxy->evaluate(sourceCode.source(), sourceCode.url().string(), WTF::toZeroBasedTextPosition(sourceCode.startPosition()), &state);
@@ -86,13 +83,21 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode,
return result;
}
-void WorkerScriptController::forbidExecution(ForbidExecutionOption option)
+void WorkerScriptController::scheduleExecutionTermination()
+{
+ v8::V8::TerminateExecution();
+}
+
+void WorkerScriptController::forbidExecution()
{
- // This function may be called from another thread.
- MutexLocker lock(m_sharedDataMutex);
+ ASSERT(m_workerContext->isContextThread());
m_executionForbidden = true;
- if (option == TerminateRunningScript)
- v8::V8::TerminateExecution();
+}
+
+bool WorkerScriptController::isExecutionForbidden() const
+{
+ ASSERT(m_workerContext->isContextThread());
+ return m_executionForbidden;
}
void WorkerScriptController::setException(ScriptValue exception)
diff --git a/Source/WebCore/bindings/v8/WorkerScriptController.h b/Source/WebCore/bindings/v8/WorkerScriptController.h
index 5e3159f..cc4b7c4 100644
--- a/Source/WebCore/bindings/v8/WorkerScriptController.h
+++ b/Source/WebCore/bindings/v8/WorkerScriptController.h
@@ -48,7 +48,7 @@ namespace WebCore {
WorkerScriptController(WorkerContext*);
~WorkerScriptController();
- WorkerContextExecutionProxy* proxy() { return m_executionForbidden ? 0 : m_proxy.get(); }
+ WorkerContextExecutionProxy* proxy() { return m_proxy.get(); }
WorkerContext* workerContext() { return m_workerContext; }
ScriptValue evaluate(const ScriptSourceCode&);
@@ -56,9 +56,17 @@ namespace WebCore {
void setException(ScriptValue);
- enum ForbidExecutionOption { TerminateRunningScript, LetRunningScriptFinish };
- void forbidExecution(ForbidExecutionOption);
- bool isExecutionForbidden() const { return m_executionForbidden; }
+ // Async request to terminate a future JS execution. Eventually causes termination
+ // exception raised during JS execution, if the worker thread happens to run JS.
+ // After JS execution was terminated in this way, the Worker thread has to use
+ // forbidExecution()/isExecutionForbidden() to guard against reentry into JS.
+ // Can be called from any thread.
+ void scheduleExecutionTermination();
+
+ // Called on Worker thread when JS exits with termination exception caused by forbidExecution() request,
+ // or by Worker thread termination code to prevent future entry into JS.
+ void forbidExecution();
+ bool isExecutionForbidden() const;
// Returns WorkerScriptController for the currently executing context. 0 will be returned if the current executing context is not the worker context.
static WorkerScriptController* controllerForContext();
@@ -66,8 +74,6 @@ namespace WebCore {
private:
WorkerContext* m_workerContext;
OwnPtr<WorkerContextExecutionProxy> m_proxy;
-
- Mutex m_sharedDataMutex;
bool m_executionForbidden;
};
diff --git a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp
index 5e2acd2..1887cea 100755
--- a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp
+++ b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp
@@ -33,21 +33,118 @@
#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
+#include "ScriptDebugListener.h"
+#include "V8DOMWrapper.h"
+#include "V8DedicatedWorkerContext.h"
+#include "V8SharedWorkerContext.h"
#include "WorkerContext.h"
+#include "WorkerContextExecutionProxy.h"
+#include "WorkerThread.h"
+#include <v8.h>
+#include <wtf/MessageQueue.h>
namespace WebCore {
+static WorkerContext* retrieveWorkerContext(v8::Handle<v8::Context> context)
+{
+ v8::Handle<v8::Object> global = context->Global();
+ ASSERT(!global.IsEmpty());
+
+ v8::Handle<v8::Object> prototype = v8::Handle<v8::Object>::Cast(global->GetPrototype());
+ ASSERT(!prototype.IsEmpty());
+
+ prototype = v8::Handle<v8::Object>::Cast(prototype->GetPrototype());
+ ASSERT(!prototype.IsEmpty());
+
+ WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(prototype);
+ if (&V8DedicatedWorkerContext::info == typeInfo)
+ return V8DedicatedWorkerContext::toNative(prototype);
+ if (&V8SharedWorkerContext::info == typeInfo)
+ return V8SharedWorkerContext::toNative(prototype);
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
WorkerScriptDebugServer::WorkerScriptDebugServer()
: ScriptDebugServer()
+ , m_pausedWorkerContext(0)
+{
+}
+
+void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener, WorkerContext* workerContext)
+{
+ v8::HandleScope scope;
+ v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
+ v8::Context::Scope contextScope(debuggerContext);
+
+ if (!m_listenersMap.size()) {
+ // FIXME: synchronize access to this code.
+ ensureDebuggerScriptCompiled();
+ ASSERT(!m_debuggerScript.get()->IsUndefined());
+ v8::Debug::SetDebugEventListener2(&WorkerScriptDebugServer::v8DebugEventCallback, v8::External::New(this));
+ }
+ m_listenersMap.set(workerContext, listener);
+
+ WorkerContextExecutionProxy* proxy = workerContext->script()->proxy();
+ if (!proxy)
+ return;
+ v8::Handle<v8::Context> context = proxy->context();
+
+ v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getWorkerScripts")));
+ v8::Handle<v8::Value> argv[] = { v8::Handle<v8::Value>() };
+ v8::Handle<v8::Value> value = getScriptsFunction->Call(m_debuggerScript.get(), 0, argv);
+ if (value.IsEmpty())
+ return;
+ ASSERT(!value->IsUndefined() && value->IsArray());
+ v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value);
+ for (unsigned i = 0; i < scriptsArray->Length(); ++i)
+ dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i))));
+}
+
+void WorkerScriptDebugServer::removeListener(ScriptDebugListener* listener, WorkerContext* workerContext)
{
+ if (!m_listenersMap.contains(workerContext))
+ return;
+
+ if (m_pausedWorkerContext == workerContext)
+ continueProgram();
+
+ m_listenersMap.remove(workerContext);
+
+ if (m_listenersMap.isEmpty())
+ v8::Debug::SetDebugEventListener2(0);
}
-void WorkerScriptDebugServer::addListener(ScriptDebugListener*, WorkerContext*)
+ScriptDebugListener* WorkerScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context> context)
{
+ WorkerContext* workerContext = retrieveWorkerContext(context);
+ if (!workerContext)
+ return 0;
+ return m_listenersMap.get(workerContext);
+}
+
+void WorkerScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context> context)
+{
+ WorkerContext* workerContext = retrieveWorkerContext(context);
+ WorkerThread* workerThread = workerContext->thread();
+
+ m_pausedWorkerContext = workerContext;
+
+ MessageQueueWaitResult result;
+ do {
+ result = workerThread->runLoop().runInMode(workerContext, "debugger");
+ // Keep waiting until execution is resumed.
+ } while (result == MessageQueueMessageReceived && isPaused());
+ m_pausedWorkerContext = 0;
+
+ // The listener may have been removed in the nested loop.
+ if (ScriptDebugListener* listener = m_listenersMap.get(workerContext))
+ listener->didContinue();
}
-void WorkerScriptDebugServer::removeListener(ScriptDebugListener*, WorkerContext*)
+void WorkerScriptDebugServer::quitMessageLoopOnPause()
{
+ // FIXME: do exit nested loop when listener is removed on pause.
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h
index fdc47ac..6264c68 100755
--- a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h
+++ b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h
@@ -49,9 +49,13 @@ public:
void removeListener(ScriptDebugListener*, WorkerContext*);
private:
- virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) { return 0; }
- virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) { }
- virtual void quitMessageLoopOnPause() { }
+ virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>);
+ virtual void runMessageLoopOnPause(v8::Handle<v8::Context>);
+ virtual void quitMessageLoopOnPause();
+
+ typedef HashMap<WorkerContext*, ScriptDebugListener*> ListenersMap;
+ ListenersMap m_listenersMap;
+ WorkerContext* m_pausedWorkerContext;
};
} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp b/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp
index 419cd60..f2f8dc0 100644
--- a/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp
@@ -51,7 +51,34 @@ v8::Handle<v8::Value> V8AudioContext::constructorCallback(const v8::Arguments& a
if (!document)
return throwError("AudioContext constructor associated document is unavailable", V8Proxy::ReferenceError);
- RefPtr<AudioContext> audioContext = AudioContext::create(document);
+ RefPtr<AudioContext> audioContext;
+
+ if (!args.Length()) {
+ // Constructor for default AudioContext which talks to audio hardware.
+ audioContext = AudioContext::create(document);
+ } else {
+ // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer.
+ // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
+ if (args.Length() < 3)
+ return throwError("Not enough arguments", V8Proxy::SyntaxError);
+
+ bool ok = false;
+
+ unsigned numberOfChannels = toInt32(args[0], ok);
+ if (!ok)
+ return throwError("Invalid number of channels", V8Proxy::SyntaxError);
+
+ unsigned numberOfFrames = toInt32(args[1], ok);
+ if (!ok)
+ return throwError("Invalid number of frames", V8Proxy::SyntaxError);
+
+ float sampleRate = toFloat(args[2]);
+
+ audioContext = AudioContext::createOfflineContext(document, numberOfChannels, numberOfFrames, sampleRate);
+ }
+
+ if (!audioContext.get())
+ return throwError("Error creating AudioContext", V8Proxy::SyntaxError);
// Transform the holder into a wrapper object for the audio context.
V8DOMWrapper::setDOMWrapper(args.Holder(), &info, audioContext.get());
diff --git a/Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp
index 850ae14..097924b 100644
--- a/Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -40,6 +40,8 @@
#include "V8Binding.h"
#include "V8Proxy.h"
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringConcatenate.h>
#include <wtf/ASCIICType.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
@@ -107,8 +109,8 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String>v8PropertyName)
if (!length)
return 0;
- Vector<UChar> name;
- name.reserveCapacity(length);
+ StringBuilder builder;
+ builder.reserveCapacity(length);
unsigned i = 0;
@@ -123,23 +125,21 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String>v8PropertyName)
} else if (hasCSSPropertyNamePrefix(propertyName, "webkit")
|| hasCSSPropertyNamePrefix(propertyName, "khtml")
|| hasCSSPropertyNamePrefix(propertyName, "apple"))
- name.append('-');
+ builder.append('-');
else if (WTF::isASCIIUpper(propertyName[0]))
return 0;
- name.append(WTF::toASCIILower(propertyName[i++]));
+ builder.append(WTF::toASCIILower(propertyName[i++]));
for (; i < length; ++i) {
UChar c = propertyName[i];
if (!WTF::isASCIIUpper(c))
- name.append(c);
- else {
- name.append('-');
- name.append(WTF::toASCIILower(c));
- }
+ builder.append(c);
+ else
+ builder.append(makeString('-', toASCIILower(c)));
}
- String propName = String::adopt(name);
+ String propName = builder.toString();
int propertyID = cssPropertyID(propName);
if (propertyID) {
propInfo = new CSSPropertyInfo();
diff --git a/Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
index 85ae322..43d5a15 100644
--- a/Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
@@ -32,6 +32,7 @@
#include "V8DOMWindow.h"
#include "Chrome.h"
+#include "ContentSecurityPolicy.h"
#include "DOMTimer.h"
#include "DOMWindow.h"
#include "ExceptionCode.h"
@@ -131,6 +132,8 @@ v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments& args, bool singl
id = DOMTimer::install(scriptContext, action, timeout, singleShot);
} else {
+ if (imp->document() && !imp->document()->contentSecurityPolicy()->allowEval())
+ return v8::Integer::New(0);
id = DOMTimer::install(scriptContext, new ScheduledAction(V8Proxy::context(imp->frame()), functionString), timeout, singleShot);
}
diff --git a/Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp
index a44131a..0889451 100644
--- a/Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8DirectoryEntryCustom.cpp
@@ -39,7 +39,7 @@
#include "V8BindingMacros.h"
#include "V8EntryCallback.h"
#include "V8ErrorCallback.h"
-#include "V8Flags.h"
+#include "V8WebKitFlags.h"
#include "V8Proxy.h"
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
@@ -55,10 +55,10 @@ v8::Handle<v8::Value> V8DirectoryEntry::getDirectoryCallback(const v8::Arguments
imp->getDirectory(path);
return v8::Handle<v8::Value>();
}
- RefPtr<Flags> flags;
- if (!isUndefinedOrNull(args[1]) && args[1]->IsObject() && !V8Flags::HasInstance(args[1])) {
+ RefPtr<WebKitFlags> flags;
+ if (!isUndefinedOrNull(args[1]) && args[1]->IsObject() && !V8WebKitFlags::HasInstance(args[1])) {
EXCEPTION_BLOCK(v8::Handle<v8::Object>, object, v8::Handle<v8::Object>::Cast(args[1]));
- flags = Flags::create();
+ flags = WebKitFlags::create();
v8::Local<v8::Value> v8Create = object->Get(v8::String::New("create"));
if (!v8Create.IsEmpty() && !isUndefinedOrNull(v8Create)) {
EXCEPTION_BLOCK(bool, isCreate, v8Create->BooleanValue());
@@ -70,7 +70,7 @@ v8::Handle<v8::Value> V8DirectoryEntry::getDirectoryCallback(const v8::Arguments
flags->setExclusive(isExclusive);
}
} else {
- EXCEPTION_BLOCK(Flags*, tmp_flags, V8Flags::HasInstance(args[1]) ? V8Flags::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0);
+ EXCEPTION_BLOCK(WebKitFlags*, tmp_flags, V8WebKitFlags::HasInstance(args[1]) ? V8WebKitFlags::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0);
flags = tmp_flags;
}
RefPtr<EntryCallback> successCallback;
@@ -98,10 +98,10 @@ v8::Handle<v8::Value> V8DirectoryEntry::getFileCallback(const v8::Arguments& arg
imp->getFile(path);
return v8::Handle<v8::Value>();
}
- RefPtr<Flags> flags;
- if (!isUndefinedOrNull(args[1]) && args[1]->IsObject() && !V8Flags::HasInstance(args[1])) {
+ RefPtr<WebKitFlags> flags;
+ if (!isUndefinedOrNull(args[1]) && args[1]->IsObject() && !V8WebKitFlags::HasInstance(args[1])) {
EXCEPTION_BLOCK(v8::Handle<v8::Object>, object, v8::Handle<v8::Object>::Cast(args[1]));
- flags = Flags::create();
+ flags = WebKitFlags::create();
v8::Local<v8::Value> v8Create = object->Get(v8::String::New("create"));
if (!v8Create.IsEmpty() && !isUndefinedOrNull(v8Create)) {
EXCEPTION_BLOCK(bool, isCreate, v8Create->BooleanValue());
@@ -113,7 +113,7 @@ v8::Handle<v8::Value> V8DirectoryEntry::getFileCallback(const v8::Arguments& arg
flags->setExclusive(isExclusive);
}
} else {
- EXCEPTION_BLOCK(Flags*, tmp_flags, V8Flags::HasInstance(args[1]) ? V8Flags::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0);
+ EXCEPTION_BLOCK(WebKitFlags*, tmp_flags, V8WebKitFlags::HasInstance(args[1]) ? V8WebKitFlags::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0);
flags = tmp_flags;
}
RefPtr<EntryCallback> successCallback;
diff --git a/Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp
index 90b3d13..cd38ca4 100644
--- a/Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8DirectoryEntrySyncCustom.cpp
@@ -40,7 +40,7 @@
#include "V8EntryCallback.h"
#include "V8ErrorCallback.h"
#include "V8FileEntrySync.h"
-#include "V8Flags.h"
+#include "V8WebKitFlags.h"
#include "V8Proxy.h"
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
@@ -62,13 +62,13 @@ static bool extractBooleanValue(const v8::Handle<v8::Object>& object, const char
return false;
}
-static PassRefPtr<Flags> getFlags(const v8::Local<v8::Value>& arg, ExceptionCode& ec)
+static PassRefPtr<WebKitFlags> getFlags(const v8::Local<v8::Value>& arg, ExceptionCode& ec)
{
ec = 0;
if (isUndefinedOrNull(arg) || !arg->IsObject())
return 0;
- if (V8Flags::HasInstance(arg))
- return V8Flags::toNative(v8::Handle<v8::Object>::Cast(arg));
+ if (V8WebKitFlags::HasInstance(arg))
+ return V8WebKitFlags::toNative(v8::Handle<v8::Object>::Cast(arg));
v8::Handle<v8::Object> object;
{
@@ -87,7 +87,7 @@ static PassRefPtr<Flags> getFlags(const v8::Local<v8::Value>& arg, ExceptionCode
if (ec)
return 0;
- RefPtr<Flags> flags = Flags::create();
+ RefPtr<WebKitFlags> flags = WebKitFlags::create();
flags->setCreate(isCreate);
flags->setExclusive(isExclusive);
@@ -100,7 +100,7 @@ v8::Handle<v8::Value> V8DirectoryEntrySync::getDirectoryCallback(const v8::Argum
DirectoryEntrySync* imp = V8DirectoryEntrySync::toNative(args.Holder());
ExceptionCode ec = 0;
STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, path, args[0]);
- RefPtr<Flags> flags = getFlags(args[1], ec);
+ RefPtr<WebKitFlags> flags = getFlags(args[1], ec);
if (UNLIKELY(ec)) {
V8Proxy::setDOMException(ec);
return v8::Handle<v8::Value>();
@@ -119,7 +119,7 @@ v8::Handle<v8::Value> V8DirectoryEntrySync::getFileCallback(const v8::Arguments&
DirectoryEntrySync* imp = V8DirectoryEntrySync::toNative(args.Holder());
ExceptionCode ec = 0;
STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, path, args[0]);
- RefPtr<Flags> flags = getFlags(args[1], ec);
+ RefPtr<WebKitFlags> flags = getFlags(args[1], ec);
if (UNLIKELY(ec)) {
V8Proxy::setDOMException(ec);
return v8::Handle<v8::Value>();
diff --git a/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
index c435863..7cad58e 100644
--- a/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
@@ -118,34 +118,6 @@ v8::Handle<v8::Value> V8Document::getCSSCanvasContextCallback(const v8::Argument
return v8::Undefined();
}
-
-// DOMImplementation is a singleton in WebCore. If we use our normal
-// mapping from DOM objects to V8 wrappers, the same wrapper will be
-// shared for all frames in the same process. This is a major
-// security problem. Therefore, we generate a DOMImplementation
-// wrapper per document and store it in an internal field of the
-// document. Since the DOMImplementation object is a singleton, we do
-// not have to do anything to keep the DOMImplementation object alive
-// for the lifetime of the wrapper.
-v8::Handle<v8::Value> V8Document::implementationAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
-{
- ASSERT(info.Holder()->InternalFieldCount() >= internalFieldCount);
-
- // Check if the internal field already contains a wrapper.
- v8::Local<v8::Value> implementation = info.Holder()->GetInternalField(V8Document::implementationIndex);
- if (!implementation->IsUndefined())
- return implementation;
-
- // Generate a wrapper.
- Document* document = V8Document::toNative(info.Holder());
- v8::Handle<v8::Value> wrapper = toV8(document->implementation());
-
- // Store the wrapper in the internal field.
- info.Holder()->SetInternalField(implementationIndex, wrapper);
-
- return wrapper;
-}
-
v8::Handle<v8::Value> toV8(Document* impl, bool forceNewObject)
{
if (!impl)
diff --git a/Source/WebCore/bindings/v8/custom/V8EventCustom.cpp b/Source/WebCore/bindings/v8/custom/V8EventCustom.cpp
index abb7d4c..7e12034 100644
--- a/Source/WebCore/bindings/v8/custom/V8EventCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8EventCustom.cpp
@@ -70,6 +70,7 @@
#if ENABLE(WEB_AUDIO)
#include "V8AudioProcessingEvent.h"
+#include "V8OfflineAudioCompletionEvent.h"
#endif
namespace WebCore {
@@ -169,6 +170,8 @@ v8::Handle<v8::Value> toV8(Event* impl)
#if ENABLE(WEB_AUDIO)
if (impl->isAudioProcessingEvent())
return toV8(static_cast<AudioProcessingEvent*>(impl));
+ if (impl->isOfflineAudioCompletionEvent())
+ return toV8(static_cast<OfflineAudioCompletionEvent*>(impl));
#endif
#if ENABLE(INPUT_SPEECH)
if (impl->isSpeechInputEvent())
diff --git a/Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp b/Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp
index 54bd11c..91389d8 100644
--- a/Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp
@@ -33,52 +33,13 @@
#include "V8Binding.h"
#include "V8CustomPositionCallback.h"
#include "V8CustomPositionErrorCallback.h"
-#include "V8Proxy.h"
+#include "V8Utilities.h"
using namespace std;
using namespace WTF;
namespace WebCore {
-static const char typeMismatchError[] = "TYPE_MISMATCH_ERR: DOM Exception 17";
-
-static void throwTypeMismatchException()
-{
- V8Proxy::throwError(V8Proxy::GeneralError, typeMismatchError);
-}
-
-static PassRefPtr<PositionCallback> createPositionCallback(v8::Local<v8::Value> value, bool& succeeded)
-{
- succeeded = true;
-
- // The spec specifies 'FunctionOnly' for this object.
- if (!value->IsFunction()) {
- succeeded = false;
- throwTypeMismatchException();
- return 0;
- }
-
- return V8CustomPositionCallback::create(value, getScriptExecutionContext());
-}
-
-static PassRefPtr<PositionErrorCallback> createPositionErrorCallback(v8::Local<v8::Value> value, bool& succeeded)
-{
- succeeded = true;
-
- // Argument is optional (hence undefined is allowed), and null is allowed.
- if (isUndefinedOrNull(value))
- return 0;
-
- // The spec specifies 'FunctionOnly' for this object.
- if (!value->IsFunction()) {
- succeeded = false;
- throwTypeMismatchException();
- return 0;
- }
-
- return V8CustomPositionErrorCallback::create(value, getScriptExecutionContext());
-}
-
static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> value, bool& succeeded)
{
succeeded = true;
@@ -172,12 +133,13 @@ v8::Handle<v8::Value> V8Geolocation::getCurrentPositionCallback(const v8::Argume
bool succeeded = false;
- RefPtr<PositionCallback> positionCallback = createPositionCallback(args[0], succeeded);
+ RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8CustomPositionCallback>(args[0], succeeded);
if (!succeeded)
return v8::Undefined();
ASSERT(positionCallback);
- RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(args[1], succeeded);
+ // Argument is optional (hence undefined is allowed), and null is allowed.
+ RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8CustomPositionErrorCallback>(args[1], succeeded, CallbackAllowUndefined | CallbackAllowNull);
if (!succeeded)
return v8::Undefined();
@@ -197,12 +159,13 @@ v8::Handle<v8::Value> V8Geolocation::watchPositionCallback(const v8::Arguments&
bool succeeded = false;
- RefPtr<PositionCallback> positionCallback = createPositionCallback(args[0], succeeded);
+ RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8CustomPositionCallback>(args[0], succeeded);
if (!succeeded)
return v8::Undefined();
ASSERT(positionCallback);
- RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(args[1], succeeded);
+ // Argument is optional (hence undefined is allowed), and null is allowed.
+ RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8CustomPositionErrorCallback>(args[1], succeeded, CallbackAllowUndefined | CallbackAllowNull);
if (!succeeded)
return v8::Undefined();
diff --git a/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp
index f4006b8..8bb4281 100644
--- a/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp
@@ -139,13 +139,13 @@ InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState* inspectedSc
v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript();
v8::Local<v8::Value> val = global->GetHiddenValue(key);
if (!val.IsEmpty() && val->IsObject())
- return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val)));
+ return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val)), m_inspectedStateAccessCheck);
- if (!canAccessInspectedWindow(inspectedScriptState))
+ if (!m_inspectedStateAccessCheck(inspectedScriptState))
return InjectedScript();
pair<long, ScriptObject> injectedScript = injectScript(injectedScriptSource(), inspectedScriptState);
- InjectedScript result(injectedScript.second);
+ InjectedScript result(injectedScript.second, m_inspectedStateAccessCheck);
m_idToInjectedScript.set(injectedScript.first, result);
global->SetHiddenValue(key, injectedScript.second.v8Object());
return result;
diff --git a/Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp b/Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp
index e5a6909..16e8cfe 100644
--- a/Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp
@@ -1,4 +1,5 @@
/*
+<<<<<<< HEAD
* Copyright (C) 2010 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,11 +27,35 @@
* 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.
+=======
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+>>>>>>> WebKit.org at r84325
*/
#include "config.h"
#include "V8Navigator.h"
+<<<<<<< HEAD
#if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED)
#include "ExceptionCode.h"
@@ -77,9 +102,49 @@ v8::Handle<v8::Value> V8Navigator::isApplicationInstalledCallback(const v8::Argu
if (!navigator->isApplicationInstalled(toWebCoreString(args[0]), callback.release()))
return throwError(INVALID_STATE_ERR);
+=======
+#if ENABLE(MEDIA_STREAM)
+
+#include "Navigator.h"
+#include "V8Binding.h"
+#include "V8NavigatorUserMediaErrorCallback.h"
+#include "V8NavigatorUserMediaSuccessCallback.h"
+#include "V8Utilities.h"
+
+using namespace WTF;
+
+namespace WebCore {
+
+v8::Handle<v8::Value> V8Navigator::webkitGetUserMediaCallback(const v8::Arguments& args)
+{
+ INC_STATS("DOM.Navigator.webkitGetUserMedia()");
+
+ v8::TryCatch exceptionCatcher;
+ String options = toWebCoreString(args[0]);
+ if (exceptionCatcher.HasCaught())
+ return throwError(exceptionCatcher.Exception());
+
+ bool succeeded = false;
+
+ RefPtr<NavigatorUserMediaSuccessCallback> successCallback = createFunctionOnlyCallback<V8NavigatorUserMediaSuccessCallback>(args[1], succeeded);
+ if (!succeeded)
+ return v8::Undefined();
+
+ // Argument is optional, hence undefined is allowed.
+ RefPtr<NavigatorUserMediaErrorCallback> errorCallback = createFunctionOnlyCallback<V8NavigatorUserMediaErrorCallback>(args[2], succeeded, CallbackAllowUndefined);
+ if (!succeeded)
+ return v8::Undefined();
+
+ Navigator* navigator = V8Navigator::toNative(args.Holder());
+ navigator->webkitGetUserMedia(options, successCallback.release(), errorCallback.release());
+>>>>>>> WebKit.org at r84325
return v8::Undefined();
}
} // namespace WebCore
+<<<<<<< HEAD
#endif // PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED)
+=======
+#endif // ENABLE(MEDIA_STREAM)
+>>>>>>> WebKit.org at r84325