Title: [218316] trunk/Source/_javascript_Core
Revision
218316
Author
[email protected]
Date
2017-06-14 22:57:27 -0700 (Wed, 14 Jun 2017)

Log Message

[Cocoa] Objective-C class whose name begins with an underscore can’t be exported to _javascript_
https://bugs.webkit.org/show_bug.cgi?id=168578

Reviewed by Geoff Garen.

* API/JSWrapperMap.mm:
(allocateConstructorForCustomClass): Updated for change to forEachProtocolImplementingProtocol.
(-[JSObjCClassInfo allocateConstructorAndPrototype]): Ditto.
(-[JSWrapperMap classInfoForClass:]): If the class name begins with an underscore, check if
  it defines conformance to a JSExport-derived protocol and if so, avoid using the
  superclass as a substitute as we’d normally do.

* API/ObjcRuntimeExtras.h:
(forEachProtocolImplementingProtocol): Added a "stop" argument to the block to let callers
  bail out.

* API/tests/JSExportTests.mm:
(+[JSExportTests classNamePrefixedWithUnderscoreTest]): New test for this.
(runJSExportTests): Run new test.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSWrapperMap.mm (218315 => 218316)


--- trunk/Source/_javascript_Core/API/JSWrapperMap.mm	2017-06-15 05:38:50 UTC (rev 218315)
+++ trunk/Source/_javascript_Core/API/JSWrapperMap.mm	2017-06-15 05:57:27 UTC (rev 218316)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015, 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -412,7 +412,7 @@
     __block HashMap<String, Protocol *> initTable;
     Protocol *exportProtocol = getJSExportProtocol();
     for (Class currentClass = cls; currentClass; currentClass = class_getSuperclass(currentClass)) {
-        forEachProtocolImplementingProtocol(currentClass, exportProtocol, ^(Protocol *protocol) {
+        forEachProtocolImplementingProtocol(currentClass, exportProtocol, ^(Protocol *protocol, bool&) {
             forEachMethodInProtocol(protocol, YES, YES, ^(SEL selector, const char*) {
                 const char* name = sel_getName(selector);
                 if (!isInitFamilyMethod(@(name)))
@@ -490,7 +490,7 @@
         putNonEnumerable(constructor, @"prototype", prototype);
 
         Protocol *exportProtocol = getJSExportProtocol();
-        forEachProtocolImplementingProtocol(m_class, exportProtocol, ^(Protocol *protocol){
+        forEachProtocolImplementingProtocol(m_class, exportProtocol, ^(Protocol *protocol, bool&){
             copyPrototypeProperties(context, m_class, protocol, prototype);
             copyMethodsToObject(context, m_class, protocol, NO, constructor);
         });
@@ -587,9 +587,17 @@
         return classInfo;
 
     // Skip internal classes beginning with '_' - just copy link to the parent class's info.
-    if ('_' == *class_getName(cls))
-        return m_classMap[cls] = [self classInfoForClass:class_getSuperclass(cls)];
+    if ('_' == *class_getName(cls)) {
+        bool conformsToExportProtocol = false;
+        forEachProtocolImplementingProtocol(cls, getJSExportProtocol(), [&conformsToExportProtocol](Protocol *, bool& stop) {
+            conformsToExportProtocol = true;
+            stop = true;
+        });
 
+        if (!conformsToExportProtocol)
+            return m_classMap[cls] = [self classInfoForClass:class_getSuperclass(cls)];
+    }
+
     return m_classMap[cls] = [[[JSObjCClassInfo alloc] initForClass:cls] autorelease];
 }
 

Modified: trunk/Source/_javascript_Core/API/ObjcRuntimeExtras.h (218315 => 218316)


--- trunk/Source/_javascript_Core/API/ObjcRuntimeExtras.h	2017-06-15 05:38:50 UTC (rev 218315)
+++ trunk/Source/_javascript_Core/API/ObjcRuntimeExtras.h	2017-06-15 05:57:27 UTC (rev 218316)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -42,7 +42,7 @@
     return false;
 }
 
-inline void forEachProtocolImplementingProtocol(Class cls, Protocol *target, void (^callback)(Protocol *))
+inline void forEachProtocolImplementingProtocol(Class cls, Protocol *target, void (^callback)(Protocol *, bool& stop))
 {
     ASSERT(cls);
     ASSERT(target);
@@ -56,6 +56,7 @@
     worklist.append(protocols, protocolsCount);
     free(protocols);
 
+    bool stop = false;
     while (!worklist.isEmpty()) {
         Protocol *protocol = worklist.last();
         worklist.removeLast();
@@ -65,8 +66,11 @@
             continue;
 
         // If it implements the protocol, make the callback.
-        if (protocolImplementsProtocol(protocol, target))
-            callback(protocol);
+        if (protocolImplementsProtocol(protocol, target)) {
+            callback(protocol, stop);
+            if (stop)
+                break;
+        }
 
         // Add incorporated protocols to the worklist.
         protocols = protocol_copyProtocolList(protocol, &protocolsCount);

Modified: trunk/Source/_javascript_Core/API/tests/JSExportTests.mm (218315 => 218316)


--- trunk/Source/_javascript_Core/API/tests/JSExportTests.mm	2017-06-15 05:38:50 UTC (rev 218315)
+++ trunk/Source/_javascript_Core/API/tests/JSExportTests.mm	2017-06-15 05:57:27 UTC (rev 218316)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -80,6 +80,28 @@
 }
 @end
 
+@interface NoUnderscorePrefix : NSObject
+@end
+
+@implementation NoUnderscorePrefix
+@end
+
+@interface _UnderscorePrefixNoExport : NoUnderscorePrefix
+@end
+
+@implementation _UnderscorePrefixNoExport
+@end
+
+@protocol Initializing <JSExport>
+- (instancetype)init;
+@end
+
+@interface _UnderscorePrefixWithExport : NoUnderscorePrefix <Initializing>
+@end
+
+@implementation _UnderscorePrefixWithExport
+@end
+
 @implementation JSExportTests
 + (void) exportInstanceMethodWithIdProtocolTest
 {
@@ -123,6 +145,21 @@
     JSValue *value = [context evaluateScript:@"myString.boolValue()"];
     checkResult(@"Dynamically generated JSExport-ed protocols are ignored", [value isUndefined] && !!context.exception);
 }
+
++ (void)classNamePrefixedWithUnderscoreTest
+{
+    JSContext *context = [[JSContext alloc] init];
+
+    context[@"_UnderscorePrefixNoExport"] = [_UnderscorePrefixNoExport class];
+    context[@"_UnderscorePrefixWithExport"] = [_UnderscorePrefixWithExport class];
+
+    checkResult(@"Non-underscore-prefixed ancestor class used when there are no exports", [context[@"_UnderscorePrefixNoExport"] toObject] == [NoUnderscorePrefix class]);
+    checkResult(@"Underscore-prefixed class used when there are exports", [context[@"_UnderscorePrefixWithExport"] toObject] == [_UnderscorePrefixWithExport class]);
+
+    JSValue *withExportInstance = [context evaluateScript:@"new _UnderscorePrefixWithExport()"];
+    checkResult(@"Exports present on underscore-prefixed class", !context.exception && !withExportInstance.isUndefined);
+}
+
 @end
 
 @protocol AJSExport <JSExport>
@@ -171,6 +208,7 @@
         [JSExportTests exportInstanceMethodWithIdProtocolTest];
         [JSExportTests exportInstanceMethodWithClassProtocolTest];
         [JSExportTests exportDynamicallyGeneratedProtocolTest];
+        [JSExportTests classNamePrefixedWithUnderscoreTest];
     }
     wrapperLifetimeIsTiedToGlobalObject();
     wrapperForNSObjectisObject();

Modified: trunk/Source/_javascript_Core/ChangeLog (218315 => 218316)


--- trunk/Source/_javascript_Core/ChangeLog	2017-06-15 05:38:50 UTC (rev 218315)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-06-15 05:57:27 UTC (rev 218316)
@@ -1,3 +1,25 @@
+2017-06-14  Dan Bernstein  <[email protected]>
+
+        [Cocoa] Objective-C class whose name begins with an underscore can’t be exported to _javascript_
+        https://bugs.webkit.org/show_bug.cgi?id=168578
+
+        Reviewed by Geoff Garen.
+
+        * API/JSWrapperMap.mm:
+        (allocateConstructorForCustomClass): Updated for change to forEachProtocolImplementingProtocol.
+        (-[JSObjCClassInfo allocateConstructorAndPrototype]): Ditto.
+        (-[JSWrapperMap classInfoForClass:]): If the class name begins with an underscore, check if
+          it defines conformance to a JSExport-derived protocol and if so, avoid using the
+          superclass as a substitute as we’d normally do.
+
+        * API/ObjcRuntimeExtras.h:
+        (forEachProtocolImplementingProtocol): Added a "stop" argument to the block to let callers
+          bail out.
+
+        * API/tests/JSExportTests.mm:
+        (+[JSExportTests classNamePrefixedWithUnderscoreTest]): New test for this.
+        (runJSExportTests): Run new test.
+
 2017-06-14  Yusuke Suzuki  <[email protected]>
 
         Unreviewed, suppress invalid register alloation validation assertion in 32 bit part 2
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to