9ffe233f4b796f5a0b95b374a483b014ed5bdd97
[WebKit-https.git] / Source / JavaScriptCore / API / tests / CustomGlobalObjectClassTest.c
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 "config.h"
27 #include "CustomGlobalObjectClassTest.h"
28
29 #include <JavaScriptCore/JSObjectRefPrivate.h>
30 #include <JavaScriptCore/JavaScript.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 extern bool assertTrue(bool value, const char* message);
36
37 static bool executedCallback = false;
38
39 static JSValueRef jsDoSomething(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef args[], JSValueRef* exception)
40 {
41     (void)function;
42     (void)thisObject;
43     (void)argc;
44     (void)args;
45     (void)exception;
46     executedCallback = true;
47     return JSValueMakeNull(ctx);
48 }
49
50 static JSStaticFunction bridgedFunctions[] = {
51     {"doSomething", jsDoSomething, kJSPropertyAttributeDontDelete},
52     {0, 0, 0},
53 };
54
55 static JSClassRef bridgedObjectClass = NULL;
56 static JSClassDefinition bridgedClassDef;
57
58 static JSClassRef jsClassRef()
59 {
60     if (!bridgedObjectClass) {
61         bridgedClassDef = kJSClassDefinitionEmpty;
62         bridgedClassDef.className = "BridgedObject";
63         bridgedClassDef.staticFunctions = bridgedFunctions;
64         bridgedObjectClass = JSClassCreate(&bridgedClassDef);
65     }
66     return bridgedObjectClass;
67 }
68
69 void customGlobalObjectClassTest()
70 {
71     JSClassRef bridgedObjectJsClassRef = jsClassRef();
72     JSGlobalContextRef globalContext = JSGlobalContextCreate(bridgedObjectJsClassRef);
73     
74     JSObjectRef globalObj = JSContextGetGlobalObject(globalContext);
75     
76     JSPropertyNameArrayRef propertyNames = JSObjectCopyPropertyNames(globalContext, globalObj);
77     size_t propertyCount = JSPropertyNameArrayGetCount(propertyNames);
78     assertTrue(propertyCount == 1, "Property count == 1");
79     
80     JSStringRef propertyNameRef = JSPropertyNameArrayGetNameAtIndex(propertyNames, 0);
81     size_t propertyNameLength = JSStringGetLength(propertyNameRef);
82     size_t bufferSize = sizeof(char) * (propertyNameLength + 1);
83     char* buffer = (char*)malloc(bufferSize);
84     JSStringGetUTF8CString(propertyNameRef, buffer, bufferSize);
85     buffer[propertyNameLength] = '\0';
86     assertTrue(!strncmp(buffer, "doSomething", propertyNameLength), "First property name is doSomething");
87     free(buffer);
88     
89     bool hasMethod = JSObjectHasProperty(globalContext, globalObj, propertyNameRef);
90     assertTrue(hasMethod, "Property found by name");
91     
92     JSValueRef doSomethingProperty =
93     JSObjectGetProperty(globalContext, globalObj, propertyNameRef, NULL);
94     assertTrue(!JSValueIsUndefined(globalContext, doSomethingProperty), "Property is defined");
95     
96     bool globalObjectClassMatchesClassRef = JSValueIsObjectOfClass(globalContext, globalObj, bridgedObjectJsClassRef);
97     assertTrue(globalObjectClassMatchesClassRef, "Global object is the right class");
98     
99     JSStringRef script = JSStringCreateWithUTF8CString("doSomething();");
100     JSEvaluateScript(globalContext, script, NULL, NULL, 1, NULL);
101     JSStringRelease(script);
102
103     assertTrue(executedCallback, "Executed custom global object callback");
104 }
105
106 void globalObjectSetPrototypeTest()
107 {
108     JSClassDefinition definition = kJSClassDefinitionEmpty;
109     definition.className = "Global";
110     JSClassRef global = JSClassCreate(&definition);
111     JSGlobalContextRef context = JSGlobalContextCreate(global);
112     JSObjectRef object = JSContextGetGlobalObject(context);
113
114     JSValueRef originalPrototype = JSObjectGetPrototype(context, object);
115     JSObjectRef above = JSObjectMake(context, 0, 0);
116     JSObjectSetPrototype(context, object, above);
117     JSValueRef prototypeAfterChangingAttempt = JSObjectGetPrototype(context, object);
118     assertTrue(JSValueIsStrictEqual(context, prototypeAfterChangingAttempt, originalPrototype), "Global object's [[Prototype]] cannot be changed after instantiating it");
119 }
120
121 void globalObjectPrivatePropertyTest()
122 {
123     JSClassDefinition definition = kJSClassDefinitionEmpty;
124     definition.className = "Global";
125     JSClassRef global = JSClassCreate(&definition);
126     JSGlobalContextRef context = JSGlobalContextCreate(global);
127     JSObjectRef globalObject = JSContextGetGlobalObject(context);
128
129     JSStringRef privateName = JSStringCreateWithUTF8CString("private");
130     JSValueRef privateValue = JSValueMakeString(context, privateName);
131     assertTrue(JSObjectSetPrivateProperty(context, globalObject, privateName, privateValue), "JSObjectSetPrivateProperty succeeded");
132     JSValueRef result = JSObjectGetPrivateProperty(context, globalObject, privateName);
133     assertTrue(JSValueIsStrictEqual(context, privateValue, result), "privateValue === \"private\"");
134
135     assertTrue(JSObjectDeletePrivateProperty(context, globalObject, privateName), "JSObjectDeletePrivateProperty succeeded");
136     result = JSObjectGetPrivateProperty(context, globalObject, privateName);
137     assertTrue(JSValueIsNull(context, result), "Deleted private property is indeed no longer present");
138
139     JSStringRelease(privateName);
140 }