JavaScriptCore:
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Jul 2006 05:05:09 +0000 (05:05 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Jul 2006 05:05:09 +0000 (05:05 +0000)
        Reviewed and tweaked a bit by Darin.

        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9902
          jsNull and NSNull not properly converted between JS and ObjC

        * bindings/objc/objc_utility.mm: (KJS::Bindings::convertObjcValueToValue):
        Added case for converting NSNull to jsNull.

LayoutTests:

        Reviewed and tweaked a bit by Darin.

        - added some new tests that use "echo" including one for JavaScript null

        * plugins/bindings-test-expected.txt: Added results.
        * plugins/bindings-test.html: Added tests.

WebCore:

        Reviewed and tweaked a bunch by Darin.

        Test: plugins/bindings-test.html

        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9902
          jsNull and NSNull not properly converted between JS and ObjC

        * bindings/objc/WebScriptObject.mm:
        (+[WebScriptObject _convertValueToObjcValue:originExecutionContext:executionContext:]):
        Added case that converts jsNull to NSNull.

WebKitTools:

        Reviewed and tweaked a bit by Darin.

        * DumpRenderTree/ObjCPlugin.m:
        (+[ObjCPlugin isSelectorExcludedFromWebScript:]): Added "echo:".
        (+[ObjCPlugin webScriptNameForSelector:]): Use the name "echo" for
        "echo:" so it's nice to call from JavaScript.
        (-[ObjCPlugin echo:]): Just returns the same object -- can be used
        to test a round trip through Objective-C types.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15618 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/bindings/objc/objc_utility.mm
LayoutTests/ChangeLog
LayoutTests/plugins/bindings-test-expected.txt
LayoutTests/plugins/bindings-test.html
WebCore/ChangeLog
WebCore/bindings/objc/WebScriptObject.mm
WebKitTools/ChangeLog
WebKitTools/DumpRenderTree/ObjCPlugin.m

index 50f09b2be9f11d1159e50a16a6890f4d6a669ea1..2c389b2d0a90e224e0fd6f839d59595c4f6ba9d1 100644 (file)
@@ -1,3 +1,13 @@
+2006-07-24  Dan Waylonis  <waylonis@google.com>
+
+        Reviewed and tweaked a bit by Darin.
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9902
+          jsNull and NSNull not properly converted between JS and ObjC
+
+        * bindings/objc/objc_utility.mm: (KJS::Bindings::convertObjcValueToValue):
+        Added case for converting NSNull to jsNull.
+
 2006-07-24  Rob Buis  <buis@kde.org>
 
         Reviewed by Darin.
index 3d5c4875fc3bc1f111943c96c3f7851f1671ef87..b3eeea57fe3afd328835b88a126089b6164fc988 100644 (file)
@@ -93,6 +93,7 @@ bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSi
     String          NSString
     wrapper         id
     Object          WebScriptObject
+    null            NSNull
     [], other       exception
 
 */
@@ -188,24 +189,25 @@ JSValue *convertNSStringToString(NSString *nsstring)
 }
 
 /*
-
     ObjC      to    JavaScript
-    char            Number
-    short
-    int
-    long
-    float
-    double
-    NSNumber        Number
-    NSString        String
-    NSArray         Array
-    id              Object wrapper
+    ----            ----------
+    char            number
+    short           number
+    int             number
+    long            number
+    float           number
+    double          number
+    NSNumber        boolean or number
+    NSString        string
+    NSArray         array
+    NSNull          null
+    WebScriptObject underlying JavaScript object
+    WebUndefined    undefined
+    id              object wrapper
     other           should not happen
-
 */
-JSValue *convertObjcValueToValue (ExecState *exec, void *buffer, ObjcValueType type)
+JSValue* convertObjcValueToValue(ExecState* exec, void* buffer, ObjcValueType type)
 {
-    JSValue *aValue = NULL;
     static ClassStructPtr webUndefinedClass = 0;
     if (!webUndefinedClass)
         webUndefinedClass = NSClassFromString(@"WebUndefined");
@@ -213,65 +215,47 @@ JSValue *convertObjcValueToValue (ExecState *exec, void *buffer, ObjcValueType t
         webScriptObjectClass = NSClassFromString(@"WebScriptObject");
 
     switch (type) {
-        case ObjcObjectType:
-            {
-                ObjectStructPtr *obj = (ObjectStructPtr *)buffer;
-
-                /*
-                    NSNumber to Number
-                    NSString to String
-                    NSArray  to Array
-                    id       to Object wrapper
-                */
-                if ([*obj isKindOfClass:[NSString class]]){
-                    aValue = convertNSStringToString((NSString *)*obj);
-                } else if ([*obj isKindOfClass:webUndefinedClass]) {
-                    return jsUndefined();
-                }  else if ((CFBooleanRef)*obj == kCFBooleanTrue) {
-                    aValue = jsBoolean(true);
-                } else if ((CFBooleanRef)*obj == kCFBooleanFalse) {
-                    aValue = jsBoolean(false);
-                } else if ([*obj isKindOfClass:[NSNumber class]]) {
-                    aValue = jsNumber([*obj doubleValue]);
-                } else if ([*obj isKindOfClass:[NSArray class]]) {
-                    aValue = new RuntimeArray(exec, new ObjcArray(*obj));
-                } else if ([*obj isKindOfClass:webScriptObjectClass]) {
-                    id<WebScriptObject> jsobject = (id<WebScriptObject>)*obj;
-                    aValue = [jsobject _imp];
-                } else if (*obj == 0) {
-                    return jsUndefined();
-                } else {
-                   aValue = Instance::createRuntimeObject(Instance::ObjectiveCLanguage, (void *)*obj);
-                }
-            }
-            break;
+        case ObjcObjectType: {
+            id obj = *(id*)buffer;
+            if ([obj isKindOfClass:[NSString class]])
+                return convertNSStringToString((NSString *)obj);
+            if ([obj isKindOfClass:webUndefinedClass])
+                return jsUndefined();
+            if ((CFBooleanRef)obj == kCFBooleanTrue)
+                return jsBoolean(true);
+            if ((CFBooleanRef)obj == kCFBooleanFalse)
+                return jsBoolean(false);
+            if ([obj isKindOfClass:[NSNumber class]])
+                return jsNumber([obj doubleValue]);
+            if ([obj isKindOfClass:[NSArray class]])
+                return new RuntimeArray(exec, new ObjcArray(obj));
+            if ([obj isKindOfClass:webScriptObjectClass])
+                return [obj _imp];
+            if ([obj isKindOfClass:[NSNull class]])
+                return jsNull();
+            if (obj == 0)
+                return jsUndefined();
+            return Instance::createRuntimeObject(Instance::ObjectiveCLanguage, obj);
+        }
         case ObjcCharType:
-            aValue = jsNumber(*(char *)buffer);
-            break;
+            return jsNumber(*(char *)buffer);
         case ObjcShortType:
-            aValue = jsNumber(*(short *)buffer);
-            break;
+            return jsNumber(*(short *)buffer);
         case ObjcIntType:
-            aValue = jsNumber(*(int *)buffer);
-            break;
+            return jsNumber(*(int *)buffer);
         case ObjcLongType:
-            aValue = jsNumber(*(long *)buffer);
-            break;
+            return jsNumber(*(long *)buffer);
         case ObjcFloatType:
-            aValue = jsNumber(*(float *)buffer);
-            break;
+            return jsNumber(*(float *)buffer);
         case ObjcDoubleType:
-            aValue = jsNumber(*(double *)buffer);
-            break;
+            return jsNumber(*(double *)buffer);
         default:
-            // Should never get here.  Argument types are filtered (and
-            // the assert above should have fired in the impossible case
-            // of an invalid type anyway).
+            // Should never get here. Argument types are filtered.
             fprintf(stderr, "%s: invalid type (%d)\n", __PRETTY_FUNCTION__, (int)type);
             assert(false);
     }
     
-    return aValue;
+    return 0;
 }
 
 
index 13e567ca39e149d0ef088bfeeb7241a531aaa09b..05f0d4046b166ed0ba5b2ee52eff94b14a61fdd1 100644 (file)
@@ -1,3 +1,12 @@
+2006-07-24  Dan Waylonis  <waylonis@google.com>
+
+        Reviewed and tweaked a bit by Darin.
+
+        - added some new tests that use "echo" including one for JavaScript null
+
+        * plugins/bindings-test-expected.txt: Added results.
+        * plugins/bindings-test.html: Added tests.
+
 2006-07-24  Darin Adler  <darin@apple.com>
 
         Reviewed by Adele and Justin.
index bb2cb72343c25ec146964498e72cf0efe7081032..e77469dbd4924ede5ace30addb96aa8eccb11702 100644 (file)
@@ -2,6 +2,14 @@ ALERT: typeof(objCPlugin)=object
 ALERT: objCPlugin()=TypeError
 ALERT: typeof(objCPluginFunction)=function
 ALERT: objCPluginFunction()=test
+ALERT: hello = hello (same)
+ALERT: string = string (same)
+ALERT: 42 = 42 (same)
+ALERT: number = number (same)
+ALERT: null = null (same)
+ALERT: object = object (same)
+ALERT: one,two = one,two (same)
+ALERT: object = object (same)
 ALERT: typeof(cPlugin)=function
 ALERT: cPlugin()=1
 ALERT: typeof(cPlugin)=object
index 59fa8b597b5deb2b24b6c1bee7b00571fe644de1..99b3cf906163b3b1dfc62a13858fca64ca06e338 100644 (file)
@@ -32,6 +32,21 @@ function doTest()
             result = e.name;
         }
         alert("objCPluginFunction()=" + result);
+
+        function echoTest(arg) {
+            var echo = objCPlugin.echo(arg);
+            var sameVal = (arg == echo) ? "same" : "different";
+            var sameType = (typeof(arg) == typeof(echo)) ? "same" : "different";
+
+            alert(arg + " = " + echo + " (" + sameVal + ")");
+            alert(typeof(arg) + " = " + typeof(echo) + " (" + sameType + ")");
+        }
+
+        // Test the echo function
+        echoTest("hello");
+        echoTest(42);
+        echoTest(null);
+        echoTest(new Array("one", "two"));
     }
     
     // Test the C plugin
index 811e1c490ad043a80eb2d5ff0f249eb01a87b5b8..df1ca4321b702399ae714f7af27878548304ca74 100644 (file)
@@ -1,3 +1,16 @@
+2006-07-24  Dan Waylonis  <waylonis@google.com>
+
+        Reviewed and tweaked a bunch by Darin.
+
+        Test: plugins/bindings-test.html
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9902
+          jsNull and NSNull not properly converted between JS and ObjC
+
+        * bindings/objc/WebScriptObject.mm:
+        (+[WebScriptObject _convertValueToObjcValue:originExecutionContext:executionContext:]):
+        Added case that converts jsNull to NSNull.
+
 2006-07-24  Darin Adler  <darin@apple.com>
 
         Reviewed by Adele and Justin.
index f07e53806ed417166abaa5ead4203c11726cbfdb..5040ec5a942e97c4c9be84982ff9e2ba6e263e71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -47,7 +47,7 @@ static void _didExecute(WebScriptObject *obj)
     ExecState *exec = [obj _executionContext]->interpreter()->globalExec();
     KJSDidExecuteFunctionPtr func = Instance::didExecuteFunction();
     if (func)
-        func (exec, static_cast<JSObject*>([obj _executionContext]->rootObjectImp()));
+        func(exec, static_cast<JSObject*>([obj _executionContext]->rootObjectImp()));
 }
 
 - (void)_initializeWithObjectImp:(JSObject *)imp originExecutionContext:(const RootObject *)originExecutionContext executionContext:(const RootObject *)executionContext
@@ -56,13 +56,12 @@ static void _didExecute(WebScriptObject *obj)
     _private->executionContext = executionContext;    
     _private->originExecutionContext = originExecutionContext;    
 
-    addNativeReference (executionContext, imp);
+    addNativeReference(executionContext, imp);
 }
 
 - _initWithJSObject:(JSObject *)imp originExecutionContext:(const RootObject *)originExecutionContext executionContext:(const RootObject *)executionContext
 {
-    assert (imp != 0);
-    //assert (root != 0);
+    assert(imp != 0);
 
     self = [super init];
 
@@ -75,11 +74,10 @@ static void _didExecute(WebScriptObject *obj)
 
 - (JSObject *)_imp
 {
-    if (!_private->imp && _private->isCreatedByDOMWrapper) {
-        // Associate the WebScriptObject with the JS wrapper for the ObjC DOM
-        // wrapper.  This is done on lazily, on demand.
+    // Associate the WebScriptObject with the JS wrapper for the ObjC DOM wrapper.
+    // This is done on lazily, on demand.
+    if (!_private->imp && _private->isCreatedByDOMWrapper)
         [self _initializeScriptDOMNodeImp];
-    }
     return _private->imp;
 }
 
@@ -108,9 +106,8 @@ static void _didExecute(WebScriptObject *obj)
 {
     if ([self _originExecutionContext]) {
        Interpreter *originInterpreter = [self _originExecutionContext]->interpreter();
-       if (originInterpreter) {
-           return originInterpreter->isSafeScript ([self _executionContext]->interpreter());
-       }
+       if (originInterpreter)
+           return originInterpreter->isSafeScript([self _executionContext]->interpreter());
     }
     return true;
 }
@@ -159,7 +156,7 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     
     for (i = 0; i < numObjects; i++) {
         id anObject = [array objectAtIndex:i];
-        aList.append (convertObjcValueToValue(exec, &anObject, ObjcObjectType));
+        aList.append(convertObjcValueToValue(exec, &anObject, ObjcObjectType));
     }
     return aList;
 }
@@ -180,7 +177,7 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     
     JSValue *v = convertObjcValueToValue(exec, &name, ObjcObjectType);
     Identifier identifier(v->toString(exec));
-    JSValue *func = [self _imp]->get (exec, identifier);
+    JSValue *func = [self _imp]->get(exec, identifier);
 
     if (!func || func->isUndefined()) {
         // Maybe throw an exception here?
@@ -191,10 +188,10 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     JSObject *funcImp = static_cast<JSObject*>(func);
     JSObject *thisObj = const_cast<JSObject*>([self _imp]);
     List argList = listFromNSArray(exec, args);
-    JSValue *result = funcImp->call (exec, thisObj, argList);
+    JSValue *result = funcImp->call(exec, thisObj, argList);
 
     if (exec->hadException()) {
-        LOG_EXCEPTION (exec);
+        LOG_EXCEPTION(exec);
         result = jsUndefined();
         exec->clearException();
     }
@@ -233,7 +230,7 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
         result = jsUndefined();
     
     if (exec->hadException()) {
-        LOG_EXCEPTION (exec);
+        LOG_EXCEPTION(exec);
         result = jsUndefined();
         exec->clearException();
     }
@@ -258,10 +255,10 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 
     JSLock lock;
     JSValue *v = convertObjcValueToValue(exec, &key, ObjcObjectType);
-    [self _imp]->put (exec, Identifier (v->toString(exec)), (convertObjcValueToValue(exec, &value, ObjcObjectType)));
+    [self _imp]->put(exec, Identifier(v->toString(exec)), convertObjcValueToValue(exec, &value, ObjcObjectType));
 
     if (exec->hadException()) {
-        LOG_EXCEPTION (exec);
+        LOG_EXCEPTION(exec);
         exec->clearException();
     }
 
@@ -281,10 +278,10 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 
     JSLock lock;
     JSValue *v = convertObjcValueToValue(exec, &key, ObjcObjectType);
-    JSValue *result = [self _imp]->get (exec, Identifier (v->toString(exec)));
+    JSValue *result = [self _imp]->get(exec, Identifier(v->toString(exec)));
     
     if (exec->hadException()) {
-        LOG_EXCEPTION (exec);
+        LOG_EXCEPTION(exec);
         result = jsUndefined();
         exec->clearException();
     }
@@ -311,10 +308,10 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 
     JSLock lock;
     JSValue *v = convertObjcValueToValue(exec, &key, ObjcObjectType);
-    [self _imp]->deleteProperty (exec, Identifier (v->toString(exec)));
+    [self _imp]->deleteProperty(exec, Identifier(v->toString(exec)));
 
     if (exec->hadException()) {
-        LOG_EXCEPTION (exec);
+        LOG_EXCEPTION(exec);
         exec->clearException();
     }
 
@@ -340,7 +337,7 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     return resultObj;
 }
 
-- (id)webScriptValueAtIndex:(unsigned int)index
+- (id)webScriptValueAtIndex:(unsigned)index
 {
     if (![self _executionContext])
         return nil;
@@ -352,10 +349,10 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     ASSERT(!exec->hadException());
 
     JSLock lock;
-    JSValue *result = [self _imp]->get (exec, (unsigned)index);
+    JSValue *result = [self _imp]->get(exec, index);
 
     if (exec->hadException()) {
-        LOG_EXCEPTION (exec);
+        LOG_EXCEPTION(exec);
         result = jsUndefined();
         exec->clearException();
     }
@@ -367,7 +364,7 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     return resultObj;
 }
 
-- (void)setWebScriptValueAtIndex:(unsigned int)index value:(id)value
+- (void)setWebScriptValueAtIndex:(unsigned)index value:(id)value
 {
     if (![self _executionContext])
         return;
@@ -379,10 +376,10 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     ASSERT(!exec->hadException());
 
     JSLock lock;
-    [self _imp]->put (exec, (unsigned)index, (convertObjcValueToValue(exec, &value, ObjcObjectType)));
+    [self _imp]->put(exec, index, convertObjcValueToValue(exec, &value, ObjcObjectType));
 
     if (exec->hadException()) {
-        LOG_EXCEPTION (exec);
+        LOG_EXCEPTION(exec);
         exec->clearException();
     }
 
@@ -400,8 +397,8 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     // First see if we have a ObjC instance.
     if (value->isObject()) {
         JSObject *objectImp = static_cast<JSObject*>(value);
-       Interpreter *intepreter = executionContext->interpreter();
-       ExecState *exec = intepreter->globalExec();
+       Interpreter *interpreter = executionContext->interpreter();
+       ExecState *exec = interpreter->globalExec();
         JSLock lock;
        
         if (objectImp->classInfo() != &RuntimeObjectImp::info) {
@@ -415,40 +412,48 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
             ObjcInstance *instance = static_cast<ObjcInstance*>(imp->getInternalInstance());
             if (instance)
                 return instance->getObject();
-        } else
-            // JS Object --> WebScriptObject
-           return (id)intepreter->createLanguageInstanceForValue (exec, Instance::ObjectiveCLanguage, value->toObject(exec), originExecutionContext, executionContext);
-    } else if (value->isString()) {
-        // JS String --> NSString
+            return nil;
+        }
+
+        // JS Object --> WebScriptObject
+        return (id)interpreter->createLanguageInstanceForValue(exec, Instance::ObjectiveCLanguage,
+            value->toObject(exec), originExecutionContext, executionContext);
+    }
+
+    if (value->isString()) {
         UString u = value->getString();
-        NSString *string = [NSString stringWithCharacters:(const unichar*)u.data() length:u.size()];
-        return string;
-    } else if (value->isNumber())
-        // JS Number --> NSNumber
+        return [NSString stringWithCharacters:(const unichar*)u.data() length:u.size()];
+    }
+
+    if (value->isNumber())
         return [NSNumber numberWithDouble:value->getNumber()];
-    else if (value->isBoolean())
-        // JS Boolean --> NSNumber
+
+    if (value->isBoolean())
         return [NSNumber numberWithBool:value->getBoolean()];
-    else if (value->isUndefined())
-        // JS Undefined --> WebUndefined
+
+    if (value->isUndefined())
         return [WebUndefined undefined];
-    
-    // Other types (UnspecifiedType and NullType) converted to 0.
-    return 0;
+
+    if (value->isNull())
+        return [NSNull null];
+  
+    // Other types (e.g., UnspecifiedType) converted to nil.
+    // This should never happen.
+    return nil;
 }
 
 @end
 
 @interface WebScriptObject (WebKitCocoaBindings)
 
-- (unsigned int)count;
-- (id)objectAtIndex:(unsigned int)index;
+- (unsigned)count;
+- (id)objectAtIndex:(unsigned)index;
 
 @end
 
 @implementation WebScriptObject (WebKitCocoaBindings)
 
-- (unsigned int)count
+- (unsigned)count
 {
     id length = [self valueForKey:@"length"];
     if ([length respondsToSelector:@selector(intValue)])
@@ -457,7 +462,7 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
         return 0;
 }
 
-- (id)objectAtIndex:(unsigned int)index
+- (id)objectAtIndex:(unsigned)index
 {
     return [self webScriptValueAtIndex:index];
 }
index 0360f8eeec7e8c4397547d0a926596a9134dcf95..c21a9987765711cad34da770ae3cb9dfd1ac58f3 100644 (file)
@@ -1,3 +1,14 @@
+2006-07-24  Dan Waylonis  <waylonis@google.com>
+
+        Reviewed and tweaked a bit by Darin.
+
+        * DumpRenderTree/ObjCPlugin.m:
+        (+[ObjCPlugin isSelectorExcludedFromWebScript:]): Added "echo:".
+        (+[ObjCPlugin webScriptNameForSelector:]): Use the name "echo" for
+        "echo:" so it's nice to call from JavaScript.
+        (-[ObjCPlugin echo:]): Just returns the same object -- can be used
+        to test a round trip through Objective-C types.
+
 2006-07-24  Alexey Proskuryakov  <ap@nypop.com>
 
         Reviewed by Darin.
index 199e895e39acb93c20c125047dac21a06d25fdbd..a68aa7ef248591bc8f6b0f021bedb9da748ce747 100644 (file)
@@ -135,11 +135,18 @@ static BOOL _allowsScriptsFullAccess = NO;
 {
     if (aSelector == @selector(removeBridgeRestrictions:))
         return NO;
+
+    if (aSelector == @selector(echo:))
+        return NO;
+
     return YES;
 }
 
 + (NSString *)webScriptNameForSelector:(SEL)aSelector
 {
+    if (aSelector == @selector(echo:))
+        return @"echo";
+  
     return nil;
 }
 
@@ -154,4 +161,9 @@ static BOOL _allowsScriptsFullAccess = NO;
     [objc release];
 }
 
+- (id)echo:(id)obj
+{
+    return obj;
+}
+
 @end