1/*
2 * Copyright (C) 2014 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. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "CustomGlobalObjectClassTest.h"
27
28#include <JavaScriptCore/JavaScriptCore.h>
29#include <stdio.h>
30
31extern bool assertTrue(bool value, const char* message);
32
33static bool executedCallback = false;
34
35static JSValueRef jsDoSomething(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef args[], JSValueRef* exception)
36{
37    (void)function;
38    (void)thisObject;
39    (void)argc;
40    (void)args;
41    (void)exception;
42    executedCallback = true;
43    return JSValueMakeNull(ctx);
44}
45
46static JSStaticFunction bridgedFunctions[] = {
47    {"doSomething", jsDoSomething, kJSPropertyAttributeDontDelete},
48    {0, 0, 0},
49};
50
51static JSClassRef bridgedObjectClass = NULL;
52static JSClassDefinition bridgedClassDef;
53
54static JSClassRef jsClassRef()
55{
56    if (!bridgedObjectClass) {
57        bridgedClassDef = kJSClassDefinitionEmpty;
58        bridgedClassDef.className = "BridgedObject";
59        bridgedClassDef.staticFunctions = bridgedFunctions;
60        bridgedObjectClass = JSClassCreate(&bridgedClassDef);
61    }
62    return bridgedObjectClass;
63}
64
65void customGlobalObjectClassTest()
66{
67    JSClassRef bridgedObjectJsClassRef = jsClassRef();
68    JSGlobalContextRef globalContext = JSGlobalContextCreate(bridgedObjectJsClassRef);
69
70    JSObjectRef globalObj = JSContextGetGlobalObject(globalContext);
71
72    JSPropertyNameArrayRef propertyNames = JSObjectCopyPropertyNames(globalContext, globalObj);
73    size_t propertyCount = JSPropertyNameArrayGetCount(propertyNames);
74    assertTrue(propertyCount == 1, "Property count == 1");
75
76    JSStringRef propertyNameRef = JSPropertyNameArrayGetNameAtIndex(propertyNames, 0);
77    size_t propertyNameLength = JSStringGetLength(propertyNameRef);
78    size_t bufferSize = sizeof(char) * (propertyNameLength + 1);
79    char* buffer = (char*)malloc(bufferSize);
80    JSStringGetUTF8CString(propertyNameRef, buffer, bufferSize);
81    buffer[propertyNameLength] = '\0';
82    assertTrue(!strncmp(buffer, "doSomething", propertyNameLength), "First property name is doSomething");
83    free(buffer);
84
85    bool hasMethod = JSObjectHasProperty(globalContext, globalObj, propertyNameRef);
86    assertTrue(hasMethod, "Property found by name");
87
88    JSValueRef doSomethingProperty =
89    JSObjectGetProperty(globalContext, globalObj, propertyNameRef, NULL);
90    assertTrue(!JSValueIsUndefined(globalContext, doSomethingProperty), "Property is defined");
91
92    bool globalObjectClassMatchesClassRef = JSValueIsObjectOfClass(globalContext, globalObj, bridgedObjectJsClassRef);
93    assertTrue(globalObjectClassMatchesClassRef, "Global object is the right class");
94
95    JSStringRef script = JSStringCreateWithUTF8CString("doSomething();");
96    JSEvaluateScript(globalContext, script, NULL, NULL, 1, NULL);
97    JSStringRelease(script);
98
99    assertTrue(executedCallback, "Executed custom global object callback");
100}
101