Diff
Modified: trunk/Source/WebCore/ChangeLog (104232 => 104233)
--- trunk/Source/WebCore/ChangeLog 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/ChangeLog 2012-01-05 23:57:26 UTC (rev 104233)
@@ -1,5 +1,47 @@
2012-01-05 Adam Barth <[email protected]>
+ [V8] CodeGeneration for SerializedScriptValue doesn't play nice with [Constructor]
+ https://bugs.webkit.org/show_bug.cgi?id=75641
+
+ Reviewed by David Levin.
+
+ Rather than generate getters for SerializedScriptValues, we eagerly
+ deserialize them into _javascript_ objects. However, previously, we were
+ only doing that for DOM wrappers created by taking an existing C++
+ object and wrapping it. For objects created with Constructors (e.g.,
+ those with the [Constructor] attribute), we need to do this eager
+ deserialization during the constructor as well.
+
+ This bug isn't observable yet, but it is causing the WebIntent test
+ being added in Bug 73051 to fail.
+
+ Test: TestSerializedScriptValueInterface.idl
+ webintents/web-intents-api.html (after Bug 73051 lands)
+
+ * bindings/scripts/CodeGeneratorV8.pm:
+ (GenerateEagerDeserialization):
+ (GenerateConstructorCallback):
+ (GenerateNamedConstructorCallback):
+ (GenerateImplementation):
+ (GenerateToV8Converters):
+ * bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:
+ (WebCore::JSTestSerializedScriptValueInterfaceConstructor::constructJSTestSerializedScriptValueInterface):
+ (WebCore::JSTestSerializedScriptValueInterfaceConstructor::getConstructData):
+ * bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h:
+ * bindings/scripts/test/TestSerializedScriptValueInterface.idl:
+ * bindings/scripts/test/V8/V8TestInterface.cpp:
+ (WebCore::V8TestInterface::constructorCallback):
+ * bindings/scripts/test/V8/V8TestNamedConstructor.cpp:
+ (WebCore::V8TestNamedConstructorConstructorCallback):
+ * bindings/scripts/test/V8/V8TestObj.cpp:
+ (WebCore::V8TestObj::constructorCallback):
+ * bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp:
+ (WebCore::V8TestSerializedScriptValueInterface::constructorCallback):
+ (WebCore::ConfigureV8TestSerializedScriptValueInterfaceTemplate):
+ * bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.h:
+
+2012-01-05 Adam Barth <[email protected]>
+
Introduce Platform namespace for WebCore/platform
https://bugs.webkit.org/show_bug.cgi?id=75653
Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm 2012-01-05 23:57:26 UTC (rev 104233)
@@ -208,6 +208,26 @@
}
}
+sub GenerateEagerDeserialization
+{
+ my $serializedAttribute = shift;
+
+ # Eagerly deserialize attributes of type SerializedScriptValue while we're
+ # in the right context.
+
+ die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue";
+ my $attrName = $serializedAttribute->signature->name;
+ my $attrAttr = "v8::DontDelete";
+ if ($serializedAttribute->type =~ /^readonly/) {
+ $attrAttr .= " | v8::ReadOnly";
+ }
+ $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)";
+ my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
+ push(@implContent, <<END);
+ SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}());
+END
+}
+
sub GetSVGPropertyTypes
{
my $implType = shift;
@@ -1561,6 +1581,7 @@
my $function = shift;
my $dataNode = shift;
my $implClassName = shift;
+ my $serializedAttribute = shift;
my $raisesExceptions = @{$function->raisesExceptions};
if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
@@ -1623,7 +1644,8 @@
my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
push(@implContent, "\n");
- push(@implContent, " RefPtr<${implClassName}> obj = ${implClassName}::create(${argumentString});\n");
+ push(@implContent, " RefPtr<${implClassName}> impl = ${implClassName}::create(${argumentString});\n");
+ push(@implContent, " v8::Handle<v8::Object> wrapper = args.Holder();\n");
if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
push(@implContent, " if (ec)\n");
@@ -1633,9 +1655,14 @@
my $DOMObject = $dataNode->extendedAttributes->{"ActiveDOMObject"} ? "ActiveDOMObject" : "DOMObject";
push(@implContent, <<END);
- V8DOMWrapper::setDOMWrapper(args.Holder(), &info, obj.get());
- obj->ref();
- V8DOMWrapper::setJSWrapperFor${DOMObject}(obj.get(), v8::Persistent<v8::Object>::New(args.Holder()));
+ V8DOMWrapper::setDOMWrapper(wrapper, &info, impl.get());
+ impl->ref();
+END
+ if ($serializedAttribute) {
+ GenerateEagerDeserialization($serializedAttribute);
+ }
+ push(@implContent, <<END);
+ V8DOMWrapper::setJSWrapperFor${DOMObject}(impl.get(), v8::Persistent<v8::Object>::New(wrapper));
return args.Holder();
END
@@ -1715,6 +1742,7 @@
my $function = shift;
my $dataNode = shift;
my $implClassName = shift;
+ my $serializedAttribute = shift;
my $raisesExceptions = @{$function->raisesExceptions};
if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
@@ -1793,7 +1821,8 @@
my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList);
push(@implContent, "\n");
- push(@implContent, " RefPtr<${implClassName}> obj = ${implClassName}::createForJSConstructor(${argumentString});\n");
+ push(@implContent, " RefPtr<${implClassName}> impl = ${implClassName}::createForJSConstructor(${argumentString});\n");
+ push(@implContent, " v8::Handle<v8::Object> wrapper = args.Holder();\n");
if ($dataNode->extendedAttributes->{"ConstructorRaisesException"}) {
push(@implContent, " if (ec)\n");
@@ -1810,9 +1839,14 @@
}
push(@implContent, <<END);
- V8DOMWrapper::setDOMWrapper(args.Holder(), &V8${implClassName}Constructor::info, obj.get());
- obj->ref();
- V8DOMWrapper::setJSWrapperFor${DOMObject}(obj.get(), v8::Persistent<v8::Object>::New(args.Holder()));
+ V8DOMWrapper::setDOMWrapper(wrapper, &V8${implClassName}Constructor::info, impl.get());
+ impl->ref();
+END
+ if ($serializedAttribute) {
+ GenerateEagerDeserialization($serializedAttribute);
+ }
+ push(@implContent, <<END);
+ V8DOMWrapper::setJSWrapperFor${DOMObject}(impl.get(), v8::Persistent<v8::Object>::New(wrapper));
return args.Holder();
END
@@ -2409,9 +2443,9 @@
push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n");
if ($dataNode->extendedAttributes->{"NamedConstructor"} && !($dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
- GenerateNamedConstructorCallback($dataNode->constructor, $dataNode, $interfaceName);
+ GenerateNamedConstructorCallback($dataNode->constructor, $dataNode, $interfaceName, $serializedAttribute);
} elsif ($dataNode->extendedAttributes->{"Constructor"} && !($dataNode->extendedAttributes->{"V8CustomConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) {
- GenerateConstructorCallback($dataNode->constructor, $dataNode, $interfaceName);
+ GenerateConstructorCallback($dataNode->constructor, $dataNode, $interfaceName, $serializedAttribute);
} elsif (IsConstructorTemplate($dataNode, "Event")) {
GenerateEventConstructorCallback($dataNode, $interfaceName);
}
@@ -3044,20 +3078,8 @@
END
push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName);
- # Eagerly deserialize attributes of type SerializedScriptValue
- # while we're in the right context.
if ($serializedAttribute) {
- die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue";
- my $attrName = $serializedAttribute->signature->name;
- my $attrAttr = "v8::DontDelete";
- if ($serializedAttribute->type =~ /^readonly/) {
- $attrAttr .= " | v8::ReadOnly";
- }
- $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)";
- my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
- push(@implContent, <<END);
- SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}());
-END
+ GenerateEagerDeserialization($serializedAttribute);
}
push(@implContent, <<END);
Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp 2012-01-05 23:57:26 UTC (rev 104233)
@@ -24,8 +24,11 @@
#include "JSTestSerializedScriptValueInterface.h"
+#include "ExceptionCode.h"
+#include "JSDOMBinding.h"
#include "SerializedScriptValue.h"
#include "TestSerializedScriptValueInterface.h"
+#include <runtime/Error.h>
#include <wtf/GetPtr.h>
using namespace JSC;
@@ -79,6 +82,27 @@
return getStaticValueDescriptor<JSTestSerializedScriptValueInterfaceConstructor, JSDOMWrapper>(exec, &JSTestSerializedScriptValueInterfaceConstructorTable, static_cast<JSTestSerializedScriptValueInterfaceConstructor*>(object), propertyName, descriptor);
}
+EncodedJSValue JSC_HOST_CALL JSTestSerializedScriptValueInterfaceConstructor::constructJSTestSerializedScriptValueInterface(ExecState* exec)
+{
+ JSTestSerializedScriptValueInterfaceConstructor* jsConstructor = static_cast<JSTestSerializedScriptValueInterfaceConstructor*>(exec->callee());
+ if (exec->argumentCount() < 2)
+ return throwVMError(exec, createTypeError(exec, "Not enough arguments"));
+ const String& hello(ustringToString(MAYBE_MISSING_PARAMETER(exec, 0, MissingIsUndefined).isEmpty() ? UString() : MAYBE_MISSING_PARAMETER(exec, 0, MissingIsUndefined).toString(exec)));
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ RefPtr<SerializedScriptValue> value(SerializedScriptValue::create(exec, MAYBE_MISSING_PARAMETER(exec, 1, MissingIsUndefined)));
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ RefPtr<TestSerializedScriptValueInterface> object = TestSerializedScriptValueInterface::create(hello, value);
+ return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), object.get())));
+}
+
+ConstructType JSTestSerializedScriptValueInterfaceConstructor::getConstructData(JSCell*, ConstructData& constructData)
+{
+ constructData.native.function = constructJSTestSerializedScriptValueInterface;
+ return ConstructTypeHost;
+}
+
/* Hash table for prototype */
static const HashTableValue JSTestSerializedScriptValueInterfacePrototypeTableValues[] =
Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h 2012-01-05 23:57:26 UTC (rev 104233)
@@ -131,6 +131,8 @@
}
protected:
static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags;
+ static JSC::EncodedJSValue JSC_HOST_CALL constructJSTestSerializedScriptValueInterface(JSC::ExecState*);
+ static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&);
};
// Attributes
Modified: trunk/Source/WebCore/bindings/scripts/test/TestSerializedScriptValueInterface.idl (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/test/TestSerializedScriptValueInterface.idl 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/test/TestSerializedScriptValueInterface.idl 2012-01-05 23:57:26 UTC (rev 104233)
@@ -28,6 +28,7 @@
module test {
interface [
Conditional=Condition1|Condition2,
+ Constructor(in DOMString hello, in SerializedScriptValue value),
] TestSerializedScriptValueInterface {
// The case of a single SerializedScriptValue attribute is a bit of a
// special case.
Modified: trunk/Source/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp 2012-01-05 23:57:26 UTC (rev 104233)
@@ -115,13 +115,14 @@
if (!context)
return throwError("TestInterface constructor's associated context is not available", V8Proxy::ReferenceError);
- RefPtr<TestInterface> obj = TestInterface::create(context, str1, str2, ec);
+ RefPtr<TestInterface> impl = TestInterface::create(context, str1, str2, ec);
+ v8::Handle<v8::Object> wrapper = args.Holder();
if (ec)
goto fail;
- V8DOMWrapper::setDOMWrapper(args.Holder(), &info, obj.get());
- obj->ref();
- V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(args.Holder()));
+ V8DOMWrapper::setDOMWrapper(wrapper, &info, impl.get());
+ impl->ref();
+ V8DOMWrapper::setJSWrapperForActiveDOMObject(impl.get(), v8::Persistent<v8::Object>::New(wrapper));
return args.Holder();
fail:
return throwError(ec);
Modified: trunk/Source/WebCore/bindings/scripts/test/V8/V8TestNamedConstructor.cpp (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/test/V8/V8TestNamedConstructor.cpp 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/test/V8/V8TestNamedConstructor.cpp 2012-01-05 23:57:26 UTC (rev 104233)
@@ -71,13 +71,14 @@
STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, str2, MAYBE_MISSING_PARAMETER(args, 1, MissingIsUndefined));
STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, str3, MAYBE_MISSING_PARAMETER(args, 2, MissingIsEmpty));
- RefPtr<TestNamedConstructor> obj = TestNamedConstructor::createForJSConstructor(document, str1, str2, str3, ec);
+ RefPtr<TestNamedConstructor> impl = TestNamedConstructor::createForJSConstructor(document, str1, str2, str3, ec);
+ v8::Handle<v8::Object> wrapper = args.Holder();
if (ec)
goto fail;
- V8DOMWrapper::setDOMWrapper(args.Holder(), &V8TestNamedConstructorConstructor::info, obj.get());
- obj->ref();
- V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(args.Holder()));
+ V8DOMWrapper::setDOMWrapper(wrapper, &V8TestNamedConstructorConstructor::info, impl.get());
+ impl->ref();
+ V8DOMWrapper::setJSWrapperForActiveDOMObject(impl.get(), v8::Persistent<v8::Object>::New(wrapper));
return args.Holder();
fail:
return throwError(ec);
Modified: trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp 2012-01-05 23:57:26 UTC (rev 104233)
@@ -1548,11 +1548,12 @@
if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
return args.Holder();
- RefPtr<TestObj> obj = TestObj::create();
+ RefPtr<TestObj> impl = TestObj::create();
+ v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::setDOMWrapper(args.Holder(), &info, obj.get());
- obj->ref();
- V8DOMWrapper::setJSWrapperForDOMObject(obj.get(), v8::Persistent<v8::Object>::New(args.Holder()));
+ V8DOMWrapper::setDOMWrapper(wrapper, &info, impl.get());
+ impl->ref();
+ V8DOMWrapper::setJSWrapperForDOMObject(impl.get(), v8::Persistent<v8::Object>::New(wrapper));
return args.Holder();
}
Modified: trunk/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp 2012-01-05 23:57:26 UTC (rev 104233)
@@ -23,9 +23,11 @@
#if ENABLE(Condition1) || ENABLE(Condition2)
+#include "ExceptionCode.h"
#include "RuntimeEnabledFeatures.h"
#include "SerializedScriptValue.h"
#include "V8Binding.h"
+#include "V8BindingMacros.h"
#include "V8BindingState.h"
#include "V8DOMWrapper.h"
#include "V8IsolatedContext.h"
@@ -42,6 +44,33 @@
} // namespace TestSerializedScriptValueInterfaceInternal
+v8::Handle<v8::Value> V8TestSerializedScriptValueInterface::constructorCallback(const v8::Arguments& args)
+{
+ INC_STATS("DOM.TestSerializedScriptValueInterface.Constructor");
+
+ if (!args.IsConstructCall())
+ return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError);
+
+ if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
+ return args.Holder();
+ if (args.Length() < 2)
+ return throwError("Not enough arguments", V8Proxy::TypeError);
+ STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, hello, MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined));
+ bool valueDidThrow = false;
+ RefPtr<SerializedScriptValue> value = SerializedScriptValue::create(args[1], 0, 0, valueDidThrow);
+ if (valueDidThrow)
+ return v8::Undefined();
+
+ RefPtr<TestSerializedScriptValueInterface> impl = TestSerializedScriptValueInterface::create(hello, value);
+ v8::Handle<v8::Object> wrapper = args.Holder();
+
+ V8DOMWrapper::setDOMWrapper(wrapper, &info, impl.get());
+ impl->ref();
+ SerializedScriptValue::deserializeAndSetProperty(wrapper, "value", static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly), impl->value());
+ V8DOMWrapper::setJSWrapperForDOMObject(impl.get(), v8::Persistent<v8::Object>::New(wrapper));
+ return args.Holder();
+}
+
static v8::Persistent<v8::FunctionTemplate> ConfigureV8TestSerializedScriptValueInterfaceTemplate(v8::Persistent<v8::FunctionTemplate> desc)
{
desc->ReadOnlyPrototype();
@@ -51,6 +80,7 @@
0, 0,
0, 0);
UNUSED_PARAM(defaultSignature); // In some cases, it will not be used.
+ desc->SetCallHandler(V8TestSerializedScriptValueInterface::constructorCallback);
// Custom toString template
Modified: trunk/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.h (104232 => 104233)
--- trunk/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.h 2012-01-05 23:45:08 UTC (rev 104232)
+++ trunk/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.h 2012-01-05 23:57:26 UTC (rev 104233)
@@ -45,6 +45,7 @@
inline static v8::Handle<v8::Object> wrap(TestSerializedScriptValueInterface*);
static void derefObject(void*);
static WrapperTypeInfo info;
+ static v8::Handle<v8::Value> constructorCallback(const v8::Arguments&);
static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + 0;
static v8::Handle<v8::Object> existingWrapper(TestSerializedScriptValueInterface*);