1 /*
2 * Copyright (C) 2008 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 "JavaScriptProfile.h"
28
29 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
30
31 #include "JavaScriptProfileNode.h"
32 #include <profiler/Profile.h>
33 #include <JavaScriptCore/APICast.h>
34 #include <JavaScriptCore/JSObjectRef.h>
35 #include <JavaScriptCore/JSStringRef.h>
36 #include <JavaScriptCore/OpaqueJSString.h>
37 #include <runtime/JSObject.h>
38 #include <runtime/JSValue.h>
39 #include <wtf/StdLibExtras.h>
40
41 using namespace JSC;
42
43 namespace WebCore {
44
45 // Cache
46
47 typedef HashMap<Profile*, JSObject*> ProfileMap;
48
profileCache()49 static ProfileMap& profileCache()
50 {
51 DEFINE_STATIC_LOCAL(ProfileMap, staticProfiles, ());
52 return staticProfiles;
53 }
54
55 // Static Values
56
57 static JSClassRef ProfileClass();
58
getTitleCallback(JSContextRef ctx,JSObjectRef thisObject,JSStringRef,JSValueRef *)59 static JSValueRef getTitleCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
60 {
61 if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
62 return JSValueMakeUndefined(ctx);
63
64 Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
65 return JSValueMakeString(ctx, OpaqueJSString::create(profile->title()).get());
66 }
67
getHeadCallback(JSContextRef ctx,JSObjectRef thisObject,JSStringRef,JSValueRef *)68 static JSValueRef getHeadCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
69 {
70 if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
71 return JSValueMakeUndefined(ctx);
72
73 ExecState* exec = toJS(ctx);
74 Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
75 return toRef(exec, toJS(exec, profile->head()));
76 }
77
getUniqueIdCallback(JSContextRef ctx,JSObjectRef thisObject,JSStringRef,JSValueRef *)78 static JSValueRef getUniqueIdCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
79 {
80 if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
81 return JSValueMakeUndefined(ctx);
82
83 Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
84 return JSValueMakeNumber(ctx, profile->uid());
85 }
86
87 // Static Functions
88
focus(JSContextRef ctx,JSObjectRef,JSObjectRef thisObject,size_t argumentCount,const JSValueRef arguments[],JSValueRef *)89 static JSValueRef focus(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
90 {
91 if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
92 return JSValueMakeUndefined(ctx);
93
94 if (argumentCount < 1)
95 return JSValueMakeUndefined(ctx);
96
97 if (!JSValueIsObjectOfClass(ctx, arguments[0], ProfileNodeClass()))
98 return JSValueMakeUndefined(ctx);
99
100 Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
101 profile->focus(static_cast<ProfileNode*>(JSObjectGetPrivate(const_cast<JSObjectRef>(arguments[0]))));
102
103 return JSValueMakeUndefined(ctx);
104 }
105
exclude(JSContextRef ctx,JSObjectRef,JSObjectRef thisObject,size_t argumentCount,const JSValueRef arguments[],JSValueRef *)106 static JSValueRef exclude(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
107 {
108 if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
109 return JSValueMakeUndefined(ctx);
110
111 if (argumentCount < 1)
112 return JSValueMakeUndefined(ctx);
113
114 if (!JSValueIsObjectOfClass(ctx, arguments[0], ProfileNodeClass()))
115 return JSValueMakeUndefined(ctx);
116
117 Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
118 profile->exclude(static_cast<ProfileNode*>(JSObjectGetPrivate(const_cast<JSObjectRef>(arguments[0]))));
119
120 return JSValueMakeUndefined(ctx);
121 }
122
restoreAll(JSContextRef ctx,JSObjectRef,JSObjectRef thisObject,size_t,const JSValueRef[],JSValueRef *)123 static JSValueRef restoreAll(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
124 {
125 if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
126 return JSValueMakeUndefined(ctx);
127
128 Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
129 profile->restoreAll();
130
131 return JSValueMakeUndefined(ctx);
132 }
133
finalize(JSObjectRef object)134 static void finalize(JSObjectRef object)
135 {
136 Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(object));
137 profileCache().remove(profile);
138 profile->deref();
139 }
140
ProfileClass()141 JSClassRef ProfileClass()
142 {
143 static JSStaticValue staticValues[] = {
144 { "title", getTitleCallback, 0, kJSPropertyAttributeNone },
145 { "head", getHeadCallback, 0, kJSPropertyAttributeNone },
146 { "uid", getUniqueIdCallback, 0, kJSPropertyAttributeNone },
147 { 0, 0, 0, 0 }
148 };
149
150 static JSStaticFunction staticFunctions[] = {
151 { "focus", focus, kJSPropertyAttributeNone },
152 { "exclude", exclude, kJSPropertyAttributeNone },
153 { "restoreAll", restoreAll, kJSPropertyAttributeNone },
154 { 0, 0, 0 }
155 };
156
157 static JSClassDefinition classDefinition = {
158 0, kJSClassAttributeNone, "Profile", 0, staticValues, staticFunctions,
159 0, finalize, 0, 0, 0, 0, 0, 0, 0, 0, 0
160 };
161
162 static JSClassRef profileClass = JSClassCreate(&classDefinition);
163 return profileClass;
164 }
165
toJS(ExecState * exec,Profile * profile)166 JSValue toJS(ExecState* exec, Profile* profile)
167 {
168 if (!profile)
169 return jsNull();
170
171 JSObject* profileWrapper = profileCache().get(profile);
172 if (profileWrapper)
173 return profileWrapper;
174
175 profile->ref();
176 profileWrapper = toJS(JSObjectMake(toRef(exec), ProfileClass(), static_cast<void*>(profile)));
177 profileCache().set(profile, profileWrapper);
178 return profileWrapper;
179 }
180
181 } // namespace WebCore
182
183 #endif // ENABLE(JAVASCRIPT_DEBUGGER)
184