/* * Copyright (C) 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #import "JSExportTests.h" #import #import #if JSC_OBJC_API_ENABLED extern "C" void checkResult(NSString *description, bool passed); @interface JSExportTests : NSObject + (void) exportInstanceMethodWithIdProtocolTest; + (void) exportInstanceMethodWithClassProtocolTest; + (void) exportDynamicallyGeneratedProtocolTest; @end @protocol TruthTeller - (BOOL) returnTrue; @end @interface TruthTeller : NSObject @end @implementation TruthTeller - (BOOL) returnTrue { return true; } @end @protocol ExportMethodWithIdProtocol - (void) methodWithIdProtocol:(id)object; @end @interface ExportMethodWithIdProtocol : NSObject @end @implementation ExportMethodWithIdProtocol - (void) methodWithIdProtocol:(id)object { checkResult(@"Exporting a method with id in the type signature", [object returnTrue]); } @end @protocol ExportMethodWithClassProtocol - (void) methodWithClassProtocol:(NSObject *)object; @end @interface ExportMethodWithClassProtocol : NSObject @end @implementation ExportMethodWithClassProtocol - (void) methodWithClassProtocol:(NSObject *)object { checkResult(@"Exporting a method with class in the type signature", [object returnTrue]); } @end @implementation JSExportTests + (void) exportInstanceMethodWithIdProtocolTest { JSContext *context = [[JSContext alloc] init]; context[@"ExportMethodWithIdProtocol"] = [ExportMethodWithIdProtocol class]; context[@"makeTestObject"] = ^{ return [[ExportMethodWithIdProtocol alloc] init]; }; context[@"opaqueObject"] = [[TruthTeller alloc] init]; [context evaluateScript:@"makeTestObject().methodWithIdProtocol(opaqueObject);"]; checkResult(@"Successfully exported instance method", !context.exception); } + (void) exportInstanceMethodWithClassProtocolTest { JSContext *context = [[JSContext alloc] init]; context[@"ExportMethodWithClassProtocol"] = [ExportMethodWithClassProtocol class]; context[@"makeTestObject"] = ^{ return [[ExportMethodWithClassProtocol alloc] init]; }; context[@"opaqueObject"] = [[TruthTeller alloc] init]; [context evaluateScript:@"makeTestObject().methodWithClassProtocol(opaqueObject);"]; checkResult(@"Successfully exported instance method", !context.exception); } + (void) exportDynamicallyGeneratedProtocolTest { JSContext *context = [[JSContext alloc] init]; Protocol *dynProtocol = objc_allocateProtocol("NSStringJSExport"); Protocol *jsExportProtocol = @protocol(JSExport); protocol_addProtocol(dynProtocol, jsExportProtocol); Method method = class_getInstanceMethod([NSString class], @selector(boolValue)); protocol_addMethodDescription(dynProtocol, @selector(boolValue), method_getTypeEncoding(method), YES, YES); NSLog(@"type encoding = %s", method_getTypeEncoding(method)); protocol_addMethodDescription(dynProtocol, @selector(boolValue), "B@:", YES, YES); objc_registerProtocol(dynProtocol); class_addProtocol([NSString class], dynProtocol); context[@"NSString"] = [NSString class]; context[@"myString"] = @"YES"; JSValue *value = [context evaluateScript:@"myString.boolValue()"]; checkResult(@"Dynamically generated JSExport-ed protocols are ignored", [value isUndefined] && !!context.exception); } @end void runJSExportTests() { @autoreleasepool { [JSExportTests exportInstanceMethodWithIdProtocolTest]; [JSExportTests exportInstanceMethodWithClassProtocolTest]; [JSExportTests exportDynamicallyGeneratedProtocolTest]; } } #endif // JSC_OBJC_API_ENABLED