Title: [111257] branches/safari-534.55-branch/Source/_javascript_Core

Diff

Modified: branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackFunction.cpp (111256 => 111257)


--- branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackFunction.cpp	2012-03-19 22:03:19 UTC (rev 111256)
+++ branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackFunction.cpp	2012-03-19 22:03:25 UTC (rev 111257)
@@ -30,7 +30,6 @@
 #include "APICast.h"
 #include "CodeBlock.h"
 #include "ExceptionHelpers.h"
-#include "JSCallbackObject.h"
 #include "JSFunction.h"
 #include "FunctionPrototype.h"
 #include <runtime/JSGlobalObject.h>
@@ -75,6 +74,10 @@
     if (exception)
         throwError(exec, toJS(exec, exception));
 
+    // result must be a valid JSValue.
+    if (!result)
+        return throwVMTypeError(exec);
+
     return JSValue::encode(toJS(exec, result));
 }
 
@@ -84,35 +87,4 @@
     return CallTypeHost;
 }
 
-JSValueRef JSCallbackFunction::toStringCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef* exception)
-{
-    JSObject* object = toJS(thisObject);
-    if (object->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
-        for (JSClassRef jsClass = jsCast<JSCallbackObject<JSNonFinalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass)
-            if (jsClass->convertToType)
-                return jsClass->convertToType(ctx, thisObject, kJSTypeString, exception);
-    } else if (object->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
-        for (JSClassRef jsClass = jsCast<JSCallbackObject<JSGlobalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass)
-            if (jsClass->convertToType)
-                return jsClass->convertToType(ctx, thisObject, kJSTypeString, exception);
-    }
-    return 0;
-}
-
-JSValueRef JSCallbackFunction::valueOfCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef* exception)
-{
-    JSObject* object = toJS(thisObject);
-    if (object->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
-        for (JSClassRef jsClass = jsCast<JSCallbackObject<JSNonFinalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass)
-            if (jsClass->convertToType)
-                return jsClass->convertToType(ctx, thisObject, kJSTypeNumber, exception);
-    } else if (object->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
-        for (JSClassRef jsClass = jsCast<JSCallbackObject<JSGlobalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass)
-            if (jsClass->convertToType)
-                return jsClass->convertToType(ctx, thisObject, kJSTypeNumber, exception);
-    }
-    return 0;
-}
-
-
 } // namespace JSC

Modified: branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackFunction.h (111256 => 111257)


--- branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackFunction.h	2012-03-19 22:03:19 UTC (rev 111256)
+++ branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackFunction.h	2012-03-19 22:03:25 UTC (rev 111257)
@@ -55,9 +55,6 @@
         return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); 
     }
 
-    static JSValueRef toStringCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
-    static JSValueRef valueOfCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
-
 private:
     static CallType getCallData(JSCell*, CallData&);
 

Modified: branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackObject.h (111256 => 111257)


--- branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackObject.h	2012-03-19 22:03:19 UTC (rev 111256)
+++ branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackObject.h	2012-03-19 22:03:25 UTC (rev 111257)
@@ -177,6 +177,8 @@
 private:
     static UString className(const JSObject*);
 
+    static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+
     static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
     static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
     

Modified: branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackObjectFunctions.h (111256 => 111257)


--- branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackObjectFunctions.h	2012-03-19 22:03:19 UTC (rev 111256)
+++ branches/safari-534.55-branch/Source/_javascript_Core/API/JSCallbackObjectFunctions.h	2012-03-19 22:03:25 UTC (rev 111257)
@@ -184,6 +184,30 @@
 }
 
 template <class Parent>
+JSValue JSCallbackObject<Parent>::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint)
+{
+    const JSCallbackObject* thisObject = jsCast<const JSCallbackObject*>(object);
+    JSContextRef ctx = toRef(exec);
+    JSObjectRef thisRef = toRef(thisObject);
+    ::JSType jsHint = hint == PreferString ? kJSTypeString : kJSTypeNumber;
+
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
+        if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
+            JSValueRef exception = 0;
+            JSValueRef result = convertToType(ctx, thisRef, jsHint, &exception);
+            if (exception) {
+                throwError(exec, toJS(exec, exception));
+                return jsUndefined();
+            }
+            if (result)
+                return toJS(exec, result);
+        }
+    }
+    
+    return Parent::defaultValue(object, exec, hint);
+}
+
+template <class Parent>
 bool JSCallbackObject<Parent>::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
     JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(object);

Modified: branches/safari-534.55-branch/Source/_javascript_Core/API/JSClassRef.cpp (111256 => 111257)


--- branches/safari-534.55-branch/Source/_javascript_Core/API/JSClassRef.cpp	2012-03-19 22:03:19 UTC (rev 111256)
+++ branches/safari-534.55-branch/Source/_javascript_Core/API/JSClassRef.cpp	2012-03-19 22:03:25 UTC (rev 111257)
@@ -214,17 +214,6 @@
      *  DerivedClass  |  DerivedClassPrototype
      */
 
-    if (convertToType) {
-        if (!prototypeClass)
-            prototypeClass = OpaqueJSClass::create(&kJSClassDefinitionEmpty).leakRef();
-        if (!prototypeClass->m_staticFunctions)
-            prototypeClass->m_staticFunctions = adoptPtr(new OpaqueJSClassStaticFunctionsTable);
-        const Identifier& toString = exec->propertyNames().toString;
-        const Identifier& valueOf = exec->propertyNames().valueOf;
-        prototypeClass->m_staticFunctions->add(StringImpl::create(toString.characters(), toString.length()), adoptPtr(new StaticFunctionEntry(&JSCallbackFunction::toStringCallback, 0)));
-        prototypeClass->m_staticFunctions->add(StringImpl::create(valueOf.characters(), valueOf.length()), adoptPtr(new StaticFunctionEntry(&JSCallbackFunction::valueOfCallback, 0)));
-    }
-
     if (!prototypeClass)
         return 0;
 

Modified: branches/safari-534.55-branch/Source/_javascript_Core/API/tests/testapi.c (111256 => 111257)


--- branches/safari-534.55-branch/Source/_javascript_Core/API/tests/testapi.c	2012-03-19 22:03:19 UTC (rev 111256)
+++ branches/safari-534.55-branch/Source/_javascript_Core/API/tests/testapi.c	2012-03-19 22:03:25 UTC (rev 111257)
@@ -311,6 +311,16 @@
     return JSValueMakeNull(context);
 }
 
+static JSValueRef MyObject_convertToTypeWrapper(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(object);
+    UNUSED_PARAM(type);
+    UNUSED_PARAM(exception);
+    // Forward to default object class
+    return 0;
+}
+
 static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
 {
     UNUSED_PARAM(ctx);
@@ -355,14 +365,65 @@
     MyObject_convertToType,
 };
 
+JSClassDefinition MyObject_convertToTypeWrapperDefinition = {
+    0,
+    kJSClassAttributeNone,
+    
+    "MyObject",
+    NULL,
+    
+    NULL,
+    NULL,
+    
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    MyObject_convertToTypeWrapper,
+};
+
+JSClassDefinition MyObject_nullWrapperDefinition = {
+    0,
+    kJSClassAttributeNone,
+    
+    "MyObject",
+    NULL,
+    
+    NULL,
+    NULL,
+    
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+};
+
 static JSClassRef MyObject_class(JSContextRef context)
 {
     UNUSED_PARAM(context);
 
     static JSClassRef jsClass;
-    if (!jsClass)
-        jsClass = JSClassCreate(&MyObject_definition);
-    
+    if (!jsClass) {
+        JSClassRef baseClass = JSClassCreate(&MyObject_definition);
+        MyObject_convertToTypeWrapperDefinition.parentClass = baseClass;
+        JSClassRef wrapperClass = JSClassCreate(&MyObject_convertToTypeWrapperDefinition);
+        MyObject_nullWrapperDefinition.parentClass = wrapperClass;
+        jsClass = JSClassCreate(&MyObject_nullWrapperDefinition);
+    }
+
     return jsClass;
 }
 

Modified: branches/safari-534.55-branch/Source/_javascript_Core/API/tests/testapi.js (111256 => 111257)


--- branches/safari-534.55-branch/Source/_javascript_Core/API/tests/testapi.js	2012-03-19 22:03:19 UTC (rev 111256)
+++ branches/safari-534.55-branch/Source/_javascript_Core/API/tests/testapi.js	2012-03-19 22:03:25 UTC (rev 111257)
@@ -155,7 +155,7 @@
 shouldBe("MyObject ? 1 : 0", true); // toBoolean
 shouldBe("+MyObject", 1); // toNumber
 shouldBe("(Object.prototype.toString.call(MyObject))", "[object MyObject]"); // Object.prototype.toString
-shouldBe("(MyObject.toString())", "MyObjectAsString"); // toString
+shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
 shouldBe("String(MyObject)", "MyObjectAsString"); // toString
 shouldBe("MyObject - 0", 1); // toNumber
 shouldBe("MyObject.valueOf()", 1); // valueOf

Modified: branches/safari-534.55-branch/Source/_javascript_Core/ChangeLog (111256 => 111257)


--- branches/safari-534.55-branch/Source/_javascript_Core/ChangeLog	2012-03-19 22:03:19 UTC (rev 111256)
+++ branches/safari-534.55-branch/Source/_javascript_Core/ChangeLog	2012-03-19 22:03:25 UTC (rev 111257)
@@ -1,5 +1,58 @@
 2012-03-19  Lucas Forschler  <[email protected]>
 
+    Merge 111162
+
+    2012-03-19  Gavin Barraclough  <[email protected]>
+
+            JSCallbackFunction::toStringCallback/valueOfCallback do not handle 0 return value from convertToType
+            https://bugs.webkit.org/show_bug.cgi?id=81468 <rdar://problem/11034745>
+
+            Reviewed by Oliver Hunt.
+
+            The API specifies that convertToType may opt not to handle a conversion:
+                "@result The objects's converted value, or NULL if the object was not converted."
+            In which case, it would propagate first up the JSClass hierarchy, calling its superclass's
+            conversion functions, and failing that call the JSObject::defaultValue function.
+
+            Unfortunately this behaviour was removed in bug#69677/bug#69858, and instead we now rely on
+            the toStringCallback/valueOfCallback function introduced in bug#69156. Even after a fix in
+            bug#73368, these will return the result from the first convertToType they find, regardless
+            of whether this result is null, and if no convertToType method is found in the api class
+            hierarchy (possible if toStringCallback/valueOfCallback was accessed off the prototype
+            chain), they will also return a null pointer. This is unsafe.
+
+            It would be easy to make the approach based around toStringCallback/valueOfCallback continue
+            to walk the api class hierarchy, but making the fallback to defaultValue would be problematic
+            (since defaultValue calls toStringCallback/valueOfCallback, this would infinitely recurse).
+            Making the fallback work with toString/valueOf methods attached to api objects is probably
+            not the right thing to do – instead, we should just implement the defaultValue trap for api
+            objects.
+
+            In addition, this bug highlights that fact that JSCallbackFunction::call will allow a hard
+            null to be returned from C to _javascript_ - this is not okay. Handle with an exception.
+
+            * API/JSCallbackFunction.cpp:
+            (JSC::JSCallbackFunction::call):
+                - Should be null checking the return value.
+            (JSC):
+                - Remove toStringCallback/valueOfCallback.
+            * API/JSCallbackFunction.h:
+            (JSCallbackFunction):
+                - Remove toStringCallback/valueOfCallback.
+            * API/JSCallbackObject.h:
+            (JSCallbackObject):
+                - Add defaultValue mthods to JSCallbackObject.
+            * API/JSCallbackObjectFunctions.h:
+            (JSC::::defaultValue):
+                - Add defaultValue mthods to JSCallbackObject.
+            * API/JSClassRef.cpp:
+            (OpaqueJSClass::prototype):
+                - Remove toStringCallback/valueOfCallback.
+            * API/tests/testapi.js:
+                - Revert this test, now we no longer artificially introduce a toString method onto the api object.
+
+2012-03-19  Lucas Forschler  <[email protected]>
+
     Merge 110818
     from http://svn.webkit.org/repository/webkit/branches/safari-534.54-branch
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to