- 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