Diff
Modified: trunk/LayoutTests/ChangeLog (145378 => 145379)
--- trunk/LayoutTests/ChangeLog 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/LayoutTests/ChangeLog 2013-03-11 19:16:01 UTC (rev 145379)
@@ -1,3 +1,14 @@
+2013-03-11 Adam Klein <[email protected]>
+
+ MutationCallback should be a WebIDL 'callback', not a [Callback] interface
+ https://bugs.webkit.org/show_bug.cgi?id=91406
+
+ Reviewed by Adam Barth.
+
+ * fast/dom/MutationObserver/mutation-observer-constructor-expected.txt:
+ * fast/dom/MutationObserver/mutation-observer-constructor.html: Add test for TypeError-throwing.
+ Note that the Number and String cases already threw before this patch.
+
2013-03-11 Julien Chaffraix <[email protected]>
[CSS Grid Layout] Handle spanning grid items over specified grid tracks
Modified: trunk/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor-expected.txt (145378 => 145379)
--- trunk/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor-expected.txt 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor-expected.txt 2013-03-11 19:16:01 UTC (rev 145379)
@@ -8,6 +8,10 @@
PASS typeof WebKitMutationObserver.prototype.disconnect is "function"
PASS typeof observer.observe is "function"
PASS typeof observer.disconnect is "function"
+PASS new MutationObserver({ handleEvent: function() {} }) threw exception TypeError: Callback argument must be a function.
+PASS new MutationObserver({}) threw exception TypeError: Callback argument must be a function.
+PASS new MutationObserver(42) threw exception TypeError: Callback argument must be a function.
+PASS new MutationObserver("foo") threw exception TypeError: Callback argument must be a function.
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor.html (145378 => 145379)
--- trunk/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor.html 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor.html 2013-03-11 19:16:01 UTC (rev 145379)
@@ -1,28 +1,20 @@
<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<script src=""
-<title></title>
-</head>
<body>
-<p id=description></p>
-<div id="console"></div>
+<script src=""
<script>
-
-function runTest() {
- shouldBeNonNull('window.WebKitMutationObserver');
- shouldBeEqualToString('typeof WebKitMutationObserver.prototype.observe', 'function');
- shouldBeEqualToString('typeof WebKitMutationObserver.prototype.disconnect', 'function');
- window.observer = new MutationObserver(function(mutations) { });
- shouldBeEqualToString('typeof observer.observe', 'function');
- shouldBeEqualToString('typeof observer.disconnect', 'function');
-}
-
description('Test the constructor of WebKitMutationObserver');
-runTest();
+shouldBeNonNull('window.WebKitMutationObserver');
+shouldBeEqualToString('typeof WebKitMutationObserver.prototype.observe', 'function');
+shouldBeEqualToString('typeof WebKitMutationObserver.prototype.disconnect', 'function');
+window.observer = new MutationObserver(function(mutations) { });
+shouldBeEqualToString('typeof observer.observe', 'function');
+shouldBeEqualToString('typeof observer.disconnect', 'function');
+
+shouldThrow('new MutationObserver({ handleEvent: function() {} })');
+shouldThrow('new MutationObserver({})');
+shouldThrow('new MutationObserver(42)');
+shouldThrow('new MutationObserver("foo")');
</script>
<script src=""
</body>
-</html>
Modified: trunk/Source/WebCore/ChangeLog (145378 => 145379)
--- trunk/Source/WebCore/ChangeLog 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/ChangeLog 2013-03-11 19:16:01 UTC (rev 145379)
@@ -1,3 +1,40 @@
+2013-03-11 Adam Klein <[email protected]>
+
+ MutationCallback should be a WebIDL 'callback', not a [Callback] interface
+ https://bugs.webkit.org/show_bug.cgi?id=91406
+
+ Reviewed by Adam Barth.
+
+ Spec: http://dom.spec.whatwg.org/#mutationcallback
+
+ Besides no longer calling handleEvent methods on passed-in objects,
+ throw a TypeError if a non-function is passed to the MutationObserver constructor.
+ This is per WebIDL: http://www.w3.org/TR/WebIDL/#es-callback-function
+
+ Updated MutationObserver constructor tests to exercise TypeError-throwing behavior.
+
+ * bindings/js/JSMutationCallback.cpp:
+ (WebCore::JSMutationCallback::call): Call the callback directly instead of handing off to JSCallbackData; make return value void.
+ Use jsArray() to convert from WTF::Vector -> JSArray.
+ * bindings/js/JSMutationCallback.h:
+ (JSMutationCallback): Rename handleEvent() to call(), make it void.
+ * bindings/js/JSMutationObserverCustom.cpp:
+ (WebCore::JSMutationObserverConstructor::constructJSMutationObserver): Throw if passed a non-function.
+ * bindings/v8/V8MutationCallback.cpp:
+ (WebCore::V8MutationCallback::V8MutationCallback): Take a v8::Function instead of a v8::Object.
+ (WebCore::V8MutationCallback::call): Call the callback directly instead of handing off to invokeCallback(); make return value void.
+ Use v8Array() to convert form WTF::Vector -> JSArray.
+ * bindings/v8/V8MutationCallback.h:
+ (WebCore::V8MutationCallback::create): Take a v8::Function instead of a v8::Object.
+ (V8MutationCallback): ditto
+ * bindings/v8/custom/V8MutationObserverCustom.cpp:
+ (WebCore::V8MutationObserver::constructorCustom): Throw if passed a non-function, cast to a v8::Function when constructing callback.
+ * dom/MutationCallback.h:
+ (WebCore): Remove unnecessary typedef.
+ (MutationCallback): Rename handleEvent() to call(), make it void.
+ * dom/MutationObserver.cpp:
+ (WebCore::MutationObserver::deliver): Update MutationCallback method name.
+
2013-03-11 Julien Chaffraix <[email protected]>
[CSS Grid Layout] Handle spanning grid items over specified grid tracks
Modified: trunk/Source/WebCore/bindings/js/JSMutationCallback.cpp (145378 => 145379)
--- trunk/Source/WebCore/bindings/js/JSMutationCallback.cpp 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/bindings/js/JSMutationCallback.cpp 2013-03-11 19:16:01 UTC (rev 145379)
@@ -27,6 +27,8 @@
#include "config.h"
#include "JSMutationCallback.h"
+#include "JSDOMGlobalObject.h"
+#include "JSMainThreadExecState.h"
#include "JSMutationObserver.h"
#include "JSMutationRecord.h"
#include "ScriptExecutionContext.h"
@@ -47,39 +49,50 @@
{
}
-bool JSMutationCallback::handleEvent(MutationRecordArray* mutations, MutationObserver* observer)
+void JSMutationCallback::call(const Vector<RefPtr<MutationRecord> >& mutations, MutationObserver* observer)
{
if (!canInvokeCallback())
- return true;
+ return;
RefPtr<JSMutationCallback> protect(this);
JSLockHolder lock(m_isolatedWorld->globalData());
if (!m_callback)
- return false;
+ return;
+ JSValue callback = m_callback.get();
+ CallData callData;
+ CallType callType = getCallData(callback, callData);
+ if (callType == CallTypeNone) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
ScriptExecutionContext* context = scriptExecutionContext();
if (!context)
- return false;
+ return;
+ ASSERT(context->isDocument());
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get());
ExecState* exec = globalObject->globalExec();
- MarkedArgumentBuffer mutationList;
- for (size_t i = 0; i < mutations->size(); ++i)
- mutationList.append(toJS(exec, globalObject, mutations->at(i).get()));
-
JSValue jsObserver = toJS(exec, globalObject, observer);
MarkedArgumentBuffer args;
- args.append(constructArray(exec, 0, globalObject, mutationList));
+ args.append(jsArray(exec, globalObject, mutations));
args.append(jsObserver);
- bool raisedException = false;
- // FIXME: Extract invokeCallback() method.
- JSCallbackData(m_callback.get(), globalObject).invokeCallback(jsObserver, args, &raisedException);
- return !raisedException;
+ globalObject->globalData().timeoutChecker.start();
+ InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);
+
+ JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args);
+
+ InspectorInstrumentation::didCallFunction(cookie);
+ globalObject->globalData().timeoutChecker.stop();
+
+ if (exec->hadException())
+ reportCurrentException(exec);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/js/JSMutationCallback.h (145378 => 145379)
--- trunk/Source/WebCore/bindings/js/JSMutationCallback.h 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/bindings/js/JSMutationCallback.h 2013-03-11 19:16:01 UTC (rev 145379)
@@ -27,12 +27,16 @@
#define JSMutationCallback_h
#include "ActiveDOMCallback.h"
-#include "JSCallbackData.h"
+#include "DOMWrapperWorld.h"
#include "MutationCallback.h"
+#include <heap/Weak.h>
+#include <runtime/JSObject.h>
#include <wtf/Forward.h>
namespace WebCore {
+class JSDOMGlobalObject;
+
class JSMutationCallback : public MutationCallback, public ActiveDOMCallback {
public:
static PassRefPtr<JSMutationCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
@@ -42,7 +46,7 @@
virtual ~JSMutationCallback();
- virtual bool handleEvent(MutationRecordArray* mutations, MutationObserver*) OVERRIDE;
+ virtual void call(const Vector<RefPtr<MutationRecord> >&, MutationObserver*) OVERRIDE;
virtual ScriptExecutionContext* scriptExecutionContext() const OVERRIDE { return ContextDestructionObserver::scriptExecutionContext(); }
Modified: trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp (145378 => 145379)
--- trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp 2013-03-11 19:16:01 UTC (rev 145379)
@@ -49,10 +49,9 @@
return throwVMError(exec, createNotEnoughArgumentsError(exec));
JSObject* object = exec->argument(0).getObject();
- if (!object) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return JSValue::encode(jsUndefined());
- }
+ CallData callData;
+ if (!object || object->methodTable()->getCallData(object, callData) == CallTypeNone)
+ return throwVMError(exec, createTypeError(exec, "Callback argument must be a function"));
JSMutationObserverConstructor* jsConstructor = jsCast<JSMutationObserverConstructor*>(exec->callee());
RefPtr<JSMutationCallback> callback = JSMutationCallback::create(object, jsConstructor->globalObject());
Modified: trunk/Source/WebCore/bindings/v8/V8MutationCallback.cpp (145378 => 145379)
--- trunk/Source/WebCore/bindings/v8/V8MutationCallback.cpp 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/bindings/v8/V8MutationCallback.cpp 2013-03-11 19:16:01 UTC (rev 145379)
@@ -26,16 +26,16 @@
#include "config.h"
#include "V8MutationCallback.h"
+#include "ScriptController.h"
#include "ScriptExecutionContext.h"
#include "V8Binding.h"
-#include "V8Callback.h"
#include "V8MutationObserver.h"
#include "V8MutationRecord.h"
#include <wtf/Assertions.h>
namespace WebCore {
-V8MutationCallback::V8MutationCallback(v8::Handle<v8::Object> callback, ScriptExecutionContext* context, v8::Handle<v8::Object> owner, v8::Isolate* isolate)
+V8MutationCallback::V8MutationCallback(v8::Handle<v8::Function> callback, ScriptExecutionContext* context, v8::Handle<v8::Object> owner, v8::Isolate* isolate)
: ActiveDOMCallback(context)
, m_callback(callback)
, m_world(DOMWrapperWorld::isolatedWorld(v8::Context::GetCurrent()))
@@ -44,44 +44,38 @@
m_callback.get().MakeWeak(isolate, this, &V8MutationCallback::weakCallback);
}
-bool V8MutationCallback::handleEvent(MutationRecordArray* mutations, MutationObserver* observer)
+void V8MutationCallback::call(const Vector<RefPtr<MutationRecord> >& mutations, MutationObserver* observer)
{
- ASSERT(mutations);
- if (!mutations)
- return true;
-
if (!canInvokeCallback())
- return true;
+ return;
v8::HandleScope handleScope;
v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_world.get());
if (v8Context.IsEmpty())
- return true;
+ return;
v8::Context::Scope scope(v8Context);
+ v8::Isolate* isolate = v8Context->GetIsolate();
- v8::Local<v8::Array> mutationsArray = v8::Array::New(mutations->size());
- for (size_t i = 0; i < mutations->size(); ++i)
- mutationsArray->Set(v8Integer(i, v8Context->GetIsolate()), toV8(mutations->at(i).get(), v8::Handle<v8::Object>(), v8Context->GetIsolate()));
+ v8::Handle<v8::Function> callback = v8::Local<v8::Function>::New(isolate, m_callback.get());
- v8::Handle<v8::Value> observerHandle = toV8(observer, v8::Handle<v8::Object>(), v8Context->GetIsolate());
+ v8::Handle<v8::Value> observerHandle = toV8(observer, v8::Handle<v8::Object>(), isolate);
if (observerHandle.IsEmpty()) {
if (!isScriptControllerTerminating())
CRASH();
- return true;
+ return;
}
if (!observerHandle->IsObject())
- return true;
+ return;
- v8::Handle<v8::Value> argv[] = {
- mutationsArray,
- observerHandle
- };
+ v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(observerHandle);
+ v8::Handle<v8::Value> argv[] = { v8Array(mutations, isolate), observerHandle };
- bool callbackReturnValue = false;
- return !invokeCallback(m_callback.get(), v8::Handle<v8::Object>::Cast(observerHandle), 2, argv, callbackReturnValue, scriptExecutionContext());
+ v8::TryCatch exceptionCatcher;
+ exceptionCatcher.SetVerbose(true);
+ ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, thisObject, 2, argv);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/v8/V8MutationCallback.h (145378 => 145379)
--- trunk/Source/WebCore/bindings/v8/V8MutationCallback.h 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/bindings/v8/V8MutationCallback.h 2013-03-11 19:16:01 UTC (rev 145379)
@@ -39,18 +39,17 @@
class V8MutationCallback : public MutationCallback, public ActiveDOMCallback {
public:
- static PassRefPtr<V8MutationCallback> create(v8::Handle<v8::Value> value, ScriptExecutionContext* context, v8::Handle<v8::Object> owner, v8::Isolate* isolate)
+ static PassRefPtr<V8MutationCallback> create(v8::Handle<v8::Function> callback, ScriptExecutionContext* context, v8::Handle<v8::Object> owner, v8::Isolate* isolate)
{
- ASSERT(value->IsObject());
ASSERT(context);
- return adoptRef(new V8MutationCallback(v8::Handle<v8::Object>::Cast(value), context, owner, isolate));
+ return adoptRef(new V8MutationCallback(callback, context, owner, isolate));
}
- virtual bool handleEvent(MutationRecordArray*, MutationObserver*) OVERRIDE;
+ virtual void call(const Vector<RefPtr<MutationRecord> >&, MutationObserver*) OVERRIDE;
virtual ScriptExecutionContext* scriptExecutionContext() const OVERRIDE { return ContextDestructionObserver::scriptExecutionContext(); }
private:
- V8MutationCallback(v8::Handle<v8::Object>, ScriptExecutionContext*, v8::Handle<v8::Object>, v8::Isolate*);
+ V8MutationCallback(v8::Handle<v8::Function>, ScriptExecutionContext*, v8::Handle<v8::Object>, v8::Isolate*);
static void weakCallback(v8::Isolate* isolate, v8::Persistent<v8::Value> wrapper, void* parameter)
{
@@ -58,7 +57,7 @@
object->m_callback.clear();
}
- ScopedPersistent<v8::Object> m_callback;
+ ScopedPersistent<v8::Function> m_callback;
RefPtr<DOMWrapperWorld> m_world;
};
Modified: trunk/Source/WebCore/bindings/v8/custom/V8MutationObserverCustom.cpp (145378 => 145379)
--- trunk/Source/WebCore/bindings/v8/custom/V8MutationObserverCustom.cpp 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/bindings/v8/custom/V8MutationObserverCustom.cpp 2013-03-11 19:16:01 UTC (rev 145379)
@@ -47,13 +47,13 @@
return throwNotEnoughArgumentsError(args.GetIsolate());
v8::Local<v8::Value> arg = args[0];
- if (!arg->IsObject())
- return setDOMException(TYPE_MISMATCH_ERR, args.GetIsolate());
+ if (!arg->IsFunction())
+ return throwTypeError("Callback argument must be a function", args.GetIsolate());
ScriptExecutionContext* context = getScriptExecutionContext();
v8::Handle<v8::Object> wrapper = args.Holder();
- RefPtr<MutationCallback> callback = V8MutationCallback::create(arg, context, wrapper, args.GetIsolate());
+ RefPtr<MutationCallback> callback = V8MutationCallback::create(v8::Handle<v8::Function>::Cast(arg), context, wrapper, args.GetIsolate());
RefPtr<MutationObserver> observer = MutationObserver::create(callback.release());
V8DOMWrapper::associateObjectWithWrapper(observer.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
Modified: trunk/Source/WebCore/dom/MutationCallback.h (145378 => 145379)
--- trunk/Source/WebCore/dom/MutationCallback.h 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/dom/MutationCallback.h 2013-03-11 19:16:01 UTC (rev 145379)
@@ -40,13 +40,11 @@
class MutationRecord;
class MutationObserver;
-typedef Vector<RefPtr<MutationRecord> > MutationRecordArray;
-
class MutationCallback : public RefCounted<MutationCallback> {
public:
virtual ~MutationCallback() { }
- virtual bool handleEvent(MutationRecordArray*, MutationObserver*) = 0;
+ virtual void call(const Vector<RefPtr<MutationRecord> >&, MutationObserver*) = 0;
virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
};
Modified: trunk/Source/WebCore/dom/MutationObserver.cpp (145378 => 145379)
--- trunk/Source/WebCore/dom/MutationObserver.cpp 2013-03-11 19:07:54 UTC (rev 145378)
+++ trunk/Source/WebCore/dom/MutationObserver.cpp 2013-03-11 19:16:01 UTC (rev 145379)
@@ -204,7 +204,7 @@
Vector<RefPtr<MutationRecord> > records;
records.swap(m_records);
- m_callback->handleEvent(&records, this);
+ m_callback->call(records, this);
}
void MutationObserver::deliverAllMutations()