/ API / tests / CurrentThisInsideBlockGetterTest.mm
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