CurrentThisInsideBlockGetterTest.mm
1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #import "config.h" 27 #import "CurrentThisInsideBlockGetterTest.h" 28 29 #if JSC_OBJC_API_ENABLED 30 31 #import <Foundation/Foundation.h> 32 #import <JavaScriptCore/JavaScriptCore.h> 33 34 static JSObjectRef CallAsConstructor(JSContextRef ctx, JSObjectRef constructor, size_t, const JSValueRef[], JSValueRef*) 35 { 36 JSObjectRef newObjectRef = NULL; 37 NSMutableDictionary *constructorPrivateProperties = (__bridge NSMutableDictionary *)(JSObjectGetPrivate(constructor)); 38 NSDictionary *constructorDescriptor = constructorPrivateProperties[@"constructorDescriptor"]; 39 newObjectRef = JSObjectMake(ctx, NULL, NULL); 40 NSDictionary *objectProperties = constructorDescriptor[@"objectProperties"]; 41 42 if (objectProperties) { 43 JSValue *newObject = [JSValue valueWithJSValueRef:newObjectRef inContext:[JSContext contextWithJSGlobalContextRef:JSContextGetGlobalContext(ctx)]]; 44 for (NSString *objectProperty in objectProperties) { 45 [newObject defineProperty:objectProperty descriptor:objectProperties[objectProperty]]; 46 } 47 } 48 49 return newObjectRef; 50 } 51 52 static void ConstructorFinalize(JSObjectRef object) 53 { 54 NSMutableDictionary *privateProperties = (__bridge NSMutableDictionary *)(JSObjectGetPrivate(object)); 55 CFBridgingRelease((__bridge CFTypeRef)(privateProperties)); 56 JSObjectSetPrivate(object, NULL); 57 } 58 59 static JSClassRef ConstructorClass(void) 60 { 61 static JSClassRef constructorClass = NULL; 62 63 if (constructorClass == NULL) { 64 JSClassDefinition classDefinition = kJSClassDefinitionEmpty; 65 classDefinition.className = "Constructor"; 66 classDefinition.callAsConstructor = CallAsConstructor; 67 classDefinition.finalize = ConstructorFinalize; 68 constructorClass = JSClassCreate(&classDefinition); 69 } 70 71 return constructorClass; 72 } 73 74 @interface JSValue (ConstructorCreation) 75 76 + (JSValue *)valueWithConstructorDescriptor:(NSDictionary *)constructorDescriptor inContext:(JSContext *)context; 77 78 @end 79 80 @implementation JSValue (ConstructorCreation) 81 82 + (JSValue *)valueWithConstructorDescriptor:(id)constructorDescriptor inContext:(JSContext *)context 83 { 84 NSMutableDictionary *privateProperties = [@{ @"constructorDescriptor" : constructorDescriptor } mutableCopy]; 85 JSGlobalContextRef ctx = [context JSGlobalContextRef]; 86 JSObjectRef constructorRef = JSObjectMake(ctx, ConstructorClass(), const_cast<void*>(CFBridgingRetain(privateProperties))); 87 JSValue *constructor = [JSValue valueWithJSValueRef:constructorRef inContext:context]; 88 return constructor; 89 } 90 91 @end 92 93 @interface JSContext (ConstructorCreation) 94 95 - (JSValue *)valueWithConstructorDescriptor:(NSDictionary *)constructorDescriptor; 96 97 @end 98 99 @implementation JSContext (ConstructorCreation) 100 101 - (JSValue *)valueWithConstructorDescriptor:(id)constructorDescriptor 102 { 103 return [JSValue valueWithConstructorDescriptor:constructorDescriptor inContext:self]; 104 } 105 106 @end 107 108 void currentThisInsideBlockGetterTest() 109 { 110 @autoreleasepool { 111 JSContext *context = [[JSContext alloc] init]; 112 113 JSValue *myConstructor = [context valueWithConstructorDescriptor:@{ 114 @"objectProperties" : @{ 115 @"currentThis" : @{ JSPropertyDescriptorGetKey : ^{ return JSContext.currentThis; } }, 116 }, 117 }]; 118 119 JSValue *myObj1 = [myConstructor constructWithArguments:nil]; 120 NSLog(@"myObj1.currentThis: %@", myObj1[@"currentThis"]); 121 JSValue *myObj2 = [myConstructor constructWithArguments:@[ @"bar" ]]; 122 NSLog(@"myObj2.currentThis: %@", myObj2[@"currentThis"]); 123 } 124 } 125 126 #endif // JSC_OBJC_API_ENABLED