Title: [161564] trunk/Source/_javascript_Core
Revision
161564
Author
[email protected]
Date
2014-01-09 11:14:55 -0800 (Thu, 09 Jan 2014)

Log Message

Constructors for Objective-C classes do not work properly with instanceof
https://bugs.webkit.org/show_bug.cgi?id=126670

Reviewed by Oliver Hunt.

This bug is due to the fact that the JS constructors created for Objective-C classes via the JSC
API inherit from JSCallbackObject, which overrides hasInstance with its own customHasInstance.
JSCallbackObject::customHasInstance only checks the JSClassRefs for hasInstance callbacks.
If it doesn't find any callbacks, it returns false.

This patch adds a hasInstance callback to constructors created for Objective-C wrapper classes.

* API/JSWrapperMap.mm:
(constructorHasInstance):
(constructorWithCustomBrand):
(allocateConstructorForCustomClass):
* API/tests/testapi.mm:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSWrapperMap.mm (161563 => 161564)


--- trunk/Source/_javascript_Core/API/JSWrapperMap.mm	2014-01-09 19:00:48 UTC (rev 161563)
+++ trunk/Source/_javascript_Core/API/JSWrapperMap.mm	2014-01-09 19:14:55 UTC (rev 161564)
@@ -98,6 +98,16 @@
     return result;
 }
 
+static bool constructorHasInstance(JSContextRef ctx, JSObjectRef constructorRef, JSValueRef possibleInstance, JSValueRef*)
+{
+    JSC::ExecState* exec = toJS(ctx);
+    JSC::APIEntryShim entryShim(exec);
+
+    JSC::JSObject* constructor = toJS(constructorRef);
+    JSC::JSValue instance = toJS(exec, possibleInstance);
+    return JSC::JSObject::defaultHasInstance(exec, instance, constructor->get(exec, exec->propertyNames().prototype));
+}
+
 static JSObjectRef makeWrapper(JSContextRef ctx, JSClassRef jsClass, id wrappedObject)
 {
     JSC::ExecState* exec = toJS(ctx);
@@ -126,6 +136,18 @@
     return [JSValue valueWithJSValueRef:result inContext:context];
 }
 
+static JSValue *constructorWithCustomBrand(JSContext *context, NSString *brand, Class cls)
+{
+    JSClassDefinition definition;
+    definition = kJSClassDefinitionEmpty;
+    definition.className = [brand UTF8String];
+    definition.hasInstance = constructorHasInstance;
+    JSClassRef classRef = JSClassCreate(&definition);
+    JSObjectRef result = makeWrapper([context JSGlobalContextRef], classRef, cls);
+    JSClassRelease(classRef);
+    return [JSValue valueWithJSValueRef:result inContext:context];
+}
+
 // Look for @optional properties in the prototype containing a selector to property
 // name mapping, separated by a __JS_EXPORT_AS__ delimiter.
 static NSMutableDictionary *createRenameMap(Protocol *protocol, BOOL isInstanceMethod)
@@ -379,7 +401,7 @@
 static JSValue *allocateConstructorForCustomClass(JSContext *context, const char* className, Class cls)
 {
     if (!supportsInitMethodConstructors())
-        return objectWithCustomBrand(context, [NSString stringWithFormat:@"%sConstructor", className], cls);
+        return constructorWithCustomBrand(context, [NSString stringWithFormat:@"%sConstructor", className], cls);
 
     // For each protocol that the class implements, gather all of the init family methods into a hash table.
     __block HashMap<String, Protocol *> initTable;
@@ -425,7 +447,7 @@
         JSObjectRef method = objCCallbackFunctionForInit(context, cls, initProtocol, initMethod, types);
         return [JSValue valueWithJSValueRef:method inContext:context];
     }
-    return objectWithCustomBrand(context, [NSString stringWithFormat:@"%sConstructor", className], cls);
+    return constructorWithCustomBrand(context, [NSString stringWithFormat:@"%sConstructor", className], cls);
 }
 
 - (void)allocateConstructorAndPrototypeWithSuperClassInfo:(JSObjCClassInfo*)superClassInfo

Modified: trunk/Source/_javascript_Core/API/tests/testapi.mm (161563 => 161564)


--- trunk/Source/_javascript_Core/API/tests/testapi.mm	2014-01-09 19:00:48 UTC (rev 161563)
+++ trunk/Source/_javascript_Core/API/tests/testapi.mm	2014-01-09 19:14:55 UTC (rev 161564)
@@ -37,6 +37,12 @@
 
 #if JSC_OBJC_API_ENABLED
 
+@interface UnexportedObject : NSObject
+@end
+
+@implementation UnexportedObject
+@end
+
 @protocol ParentObject <JSExport>
 @end
 
@@ -1216,6 +1222,16 @@
         checkResult(@"fetched context.name was expected", ![fetchedName1 isEqualToString:fetchedName2]);
     }
 
+    @autoreleasepool {
+        JSContext *context = [[JSContext alloc] init];
+        context[@"UnexportedObject"] = [UnexportedObject class];
+        context[@"makeObject"] = ^{
+            return [[UnexportedObject alloc] init];
+        };
+        JSValue *result = [context evaluateScript:@"(makeObject() instanceof UnexportedObject)"];
+        checkResult(@"makeObject() instanceof UnexportedObject", [result isBoolean] && [result toBool]);
+    }
+
     currentThisInsideBlockGetterTest();
 }
 

Modified: trunk/Source/_javascript_Core/ChangeLog (161563 => 161564)


--- trunk/Source/_javascript_Core/ChangeLog	2014-01-09 19:00:48 UTC (rev 161563)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-01-09 19:14:55 UTC (rev 161564)
@@ -1,3 +1,23 @@
+2014-01-09  Mark Hahnenberg  <[email protected]>
+
+        Constructors for Objective-C classes do not work properly with instanceof
+        https://bugs.webkit.org/show_bug.cgi?id=126670
+
+        Reviewed by Oliver Hunt.
+
+        This bug is due to the fact that the JS constructors created for Objective-C classes via the JSC 
+        API inherit from JSCallbackObject, which overrides hasInstance with its own customHasInstance. 
+        JSCallbackObject::customHasInstance only checks the JSClassRefs for hasInstance callbacks. 
+        If it doesn't find any callbacks, it returns false.
+
+        This patch adds a hasInstance callback to constructors created for Objective-C wrapper classes.
+
+        * API/JSWrapperMap.mm:
+        (constructorHasInstance):
+        (constructorWithCustomBrand):
+        (allocateConstructorForCustomClass):
+        * API/tests/testapi.mm:
+
 2014-01-09  Joseph Pecoraro  <[email protected]>
 
         Web Inspector: Move InjectedScript classes into _javascript_Core
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to