Bug 846: Separate JS_GetParent & JS_GetPrivate calls from initializations.
[elinks.git] / src / scripting / smjs / globhist.c
blob1b87c2eba4c23e13b00f491fb2259e7e47ed182c
1 /* "elinks.globhist" */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include "elinks.h"
9 #include "globhist/globhist.h"
10 #include "ecmascript/spidermonkey/util.h"
11 #include "scripting/smjs/core.h"
12 #include "scripting/smjs/elinks_object.h"
13 #include "util/memory.h"
16 /* @smjs_globhist_item_class.finalize */
17 static void
18 smjs_globhist_item_finalize(JSContext *ctx, JSObject *obj)
20 struct global_history_item *history_item;
22 history_item = JS_GetPrivate(ctx, obj); /* from @smjs_globhist_item_class */
24 if (history_item) object_unlock(history_item);
27 enum smjs_globhist_item_prop {
28 GLOBHIST_TITLE,
29 GLOBHIST_URL,
30 GLOBHIST_LAST_VISIT,
33 static const JSPropertySpec smjs_globhist_item_props[] = {
34 { "title", GLOBHIST_TITLE, JSPROP_ENUMERATE },
35 { "url", GLOBHIST_URL, JSPROP_ENUMERATE },
36 { "last_visit", GLOBHIST_LAST_VISIT, JSPROP_ENUMERATE },
37 { NULL }
40 /* @smjs_globhist_item_class.getProperty */
41 static JSBool
42 smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id,
43 jsval *vp)
45 struct global_history_item *history_item;
47 history_item = JS_GetPrivate(ctx, obj); /* from @smjs_globhist_item_class */
49 if (!history_item) return JS_FALSE;
51 undef_to_jsval(ctx, vp);
53 if (!JSVAL_IS_INT(id))
54 return JS_FALSE;
56 switch (JSVAL_TO_INT(id)) {
57 case GLOBHIST_TITLE:
58 *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
59 history_item->title));
61 return JS_TRUE;
62 case GLOBHIST_URL:
63 *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
64 history_item->url));
66 return JS_TRUE;
67 case GLOBHIST_LAST_VISIT:
68 /* TODO: I'd rather return a date object, but that introduces
69 * synchronisation issues:
71 * - How do we cause a change to that date object to affect
72 * the actual global history item?
73 * - How do we get a change to that global history item
74 * to affect all date objects?
76 * The biggest obstacle is that we have no way to trigger code
77 * when one messes with the date object.
79 * -- Miciah */
80 /* XXX: Currently, ECMAScript gets seconds since the epoch.
81 * Since the Date object uses milliseconds since the epoch,
82 * I'd rather export that, but SpiderMonkey doesn't provide
83 * a suitable type. -- Miciah */
84 JS_NewNumberValue(smjs_ctx, history_item->last_visit, vp);
86 return JS_TRUE;
87 default:
88 INTERNAL("Invalid ID %d in globhist_get_property().",
89 JSVAL_TO_INT(id));
92 return JS_FALSE;
95 /* @smjs_globhist_item_class.setProperty */
96 static JSBool
97 smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
99 struct global_history_item *history_item;
101 history_item = JS_GetPrivate(ctx, obj); /* from @smjs_globhist_item_class */
103 if (!history_item) return JS_FALSE;
105 if (!JSVAL_IS_INT(id))
106 return JS_FALSE;
108 switch (JSVAL_TO_INT(id)) {
109 case GLOBHIST_TITLE: {
110 JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
111 unsigned char *str = JS_GetStringBytes(jsstr);
113 mem_free_set(&history_item->title, stracpy(str));
115 return JS_TRUE;
117 case GLOBHIST_URL: {
118 JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
119 unsigned char *str = JS_GetStringBytes(jsstr);
121 mem_free_set(&history_item->url, stracpy(str));
123 return JS_TRUE;
125 case GLOBHIST_LAST_VISIT: {
126 uint32 seconds;
128 JS_ValueToECMAUint32(smjs_ctx, *vp, &seconds);
129 history_item->last_visit = seconds;
131 return JS_TRUE;
133 default:
134 INTERNAL("Invalid ID %d in bookmark_set_property().",
135 JSVAL_TO_INT(id));
138 return JS_FALSE;
141 static const JSClass smjs_globhist_item_class = {
142 "global_history_item",
143 JSCLASS_HAS_PRIVATE, /* struct global_history_item * */
144 JS_PropertyStub, JS_PropertyStub,
145 smjs_globhist_item_get_property, smjs_globhist_item_set_property,
146 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
147 smjs_globhist_item_finalize,
150 static JSObject *
151 smjs_get_globhist_item_object(struct global_history_item *history_item)
153 JSObject *jsobj;
155 jsobj = JS_NewObject(smjs_ctx, (JSClass *) &smjs_globhist_item_class,
156 NULL, NULL);
157 if (!jsobj
158 || JS_TRUE != JS_DefineProperties(smjs_ctx, jsobj,
159 (JSPropertySpec *) smjs_globhist_item_props)
160 || JS_TRUE != JS_SetPrivate(smjs_ctx, jsobj, history_item)) /* to @smjs_globhist_item_class */
161 return NULL;
163 object_lock(history_item);
165 return jsobj;
169 /* @smjs_globhist_class.getProperty */
170 static JSBool
171 smjs_globhist_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
173 JSObject *jsobj;
174 unsigned char *uri_string;
175 struct global_history_item *history_item;
177 uri_string = JS_GetStringBytes(JS_ValueToString(ctx, id));
178 if (!uri_string) goto ret_null;
180 history_item = get_global_history_item(uri_string);
181 if (!history_item) goto ret_null;
183 jsobj = smjs_get_globhist_item_object(history_item);
184 if (!jsobj) goto ret_null;
186 *vp = OBJECT_TO_JSVAL(jsobj);
188 return JS_TRUE;
190 ret_null:
191 *vp = JSVAL_NULL;
193 return JS_TRUE;
196 static const JSClass smjs_globhist_class = {
197 "global_history", 0,
198 JS_PropertyStub, JS_PropertyStub,
199 smjs_globhist_get_property, JS_PropertyStub,
200 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
203 static JSObject *
204 smjs_get_globhist_object(void)
206 JSObject *globhist;
208 globhist = JS_NewObject(smjs_ctx, (JSClass *) &smjs_globhist_class,
209 NULL, NULL);
210 if (!globhist) return NULL;
212 return globhist;
215 void
216 smjs_init_globhist_interface(void)
218 jsval val;
219 struct JSObject *globhist;
221 if (!smjs_ctx || !smjs_elinks_object)
222 return;
224 globhist = smjs_get_globhist_object();
225 if (!globhist) return;
227 val = OBJECT_TO_JSVAL(globhist);
229 JS_SetProperty(smjs_ctx, smjs_elinks_object, "globhist", &val);