1 /* "elinks.globhist" */
9 #include "globhist/globhist.h"
10 #include "ecmascript/spidermonkey-shared.h"
11 #include "scripting/smjs/core.h"
12 #include "scripting/smjs/elinks_object.h"
13 #include "util/memory.h"
16 static const JSClass smjs_globhist_item_class
; /* defined below */
19 /* @smjs_globhist_item_class.finalize */
21 smjs_globhist_item_finalize(JSContext
*ctx
, JSObject
*obj
)
23 struct global_history_item
*history_item
;
25 assert(JS_InstanceOf(ctx
, obj
, (JSClass
*) &smjs_globhist_item_class
, NULL
));
26 if_assert_failed
return;
28 history_item
= JS_GetInstancePrivate(ctx
, obj
,
29 (JSClass
*) &smjs_globhist_item_class
,
32 if (history_item
) object_unlock(history_item
);
35 /* Tinyids of properties. Use negative values to distinguish these
36 * from array indexes (even though this object has no array elements).
37 * ECMAScript code should not use these directly as in global_history_item[-1];
38 * future future versions of ELinks may change the numbers. */
39 enum smjs_globhist_item_prop
{
42 GLOBHIST_LAST_VISIT
= -3,
45 static const JSPropertySpec smjs_globhist_item_props
[] = {
46 { "title", GLOBHIST_TITLE
, JSPROP_ENUMERATE
},
47 { "url", GLOBHIST_URL
, JSPROP_ENUMERATE
},
48 { "last_visit", GLOBHIST_LAST_VISIT
, JSPROP_ENUMERATE
},
52 /* @smjs_globhist_item_class.getProperty */
54 smjs_globhist_item_get_property(JSContext
*ctx
, JSObject
*obj
, jsid id
,
57 struct global_history_item
*history_item
;
59 /* This can be called if @obj if not itself an instance of the
60 * appropriate class but has one in its prototype chain. Fail
62 if (!JS_InstanceOf(ctx
, obj
, (JSClass
*) &smjs_globhist_item_class
, NULL
))
65 history_item
= JS_GetInstancePrivate(ctx
, obj
,
66 (JSClass
*) &smjs_globhist_item_class
,
69 if (!history_item
) return JS_FALSE
;
71 undef_to_jsval(ctx
, vp
);
76 switch (JSID_TO_INT(id
)) {
78 *vp
= STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx
,
79 history_item
->title
));
83 *vp
= STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx
,
87 case GLOBHIST_LAST_VISIT
:
88 /* TODO: I'd rather return a date object, but that introduces
89 * synchronisation issues:
91 * - How do we cause a change to that date object to affect
92 * the actual global history item?
93 * - How do we get a change to that global history item
94 * to affect all date objects?
96 * The biggest obstacle is that we have no way to trigger code
97 * when one messes with the date object.
100 /* XXX: Currently, ECMAScript gets seconds since the epoch.
101 * Since the Date object uses milliseconds since the epoch,
102 * I'd rather export that, but SpiderMonkey doesn't provide
103 * a suitable type. -- Miciah */
104 JS_NewNumberValue(smjs_ctx
, history_item
->last_visit
, vp
);
108 /* Unrecognized integer property ID; someone is using
109 * the object as an array. SMJS builtin classes (e.g.
110 * js_RegExpClass) just return JS_TRUE in this case
111 * and leave *@vp unchanged. Do the same here.
112 * (Actually not quite the same, as we already used
113 * @undef_to_jsval.) */
118 /* @smjs_globhist_item_class.setProperty */
120 smjs_globhist_item_set_property(JSContext
*ctx
, JSObject
*obj
, jsid id
, JSBool strict
, jsval
*vp
)
122 struct global_history_item
*history_item
;
124 /* This can be called if @obj if not itself an instance of the
125 * appropriate class but has one in its prototype chain. Fail
127 if (!JS_InstanceOf(ctx
, obj
, (JSClass
*) &smjs_globhist_item_class
, NULL
))
130 history_item
= JS_GetInstancePrivate(ctx
, obj
,
131 (JSClass
*) &smjs_globhist_item_class
,
134 if (!history_item
) return JS_FALSE
;
136 if (!JSID_IS_INT(id
))
139 switch (JSID_TO_INT(id
)) {
140 case GLOBHIST_TITLE
: {
141 JSString
*jsstr
= JS_ValueToString(smjs_ctx
, *vp
);
142 unsigned char *str
= JS_EncodeString(smjs_ctx
, jsstr
);
144 mem_free_set(&history_item
->title
, stracpy(str
));
149 JSString
*jsstr
= JS_ValueToString(smjs_ctx
, *vp
);
150 unsigned char *str
= JS_EncodeString(smjs_ctx
, jsstr
);
152 mem_free_set(&history_item
->url
, stracpy(str
));
156 case GLOBHIST_LAST_VISIT
: {
159 /* Bug 923: Assumes time_t values fit in uint32. */
160 JS_ValueToECMAUint32(smjs_ctx
, *vp
, &seconds
);
161 history_item
->last_visit
= seconds
;
166 /* Unrecognized integer property ID; someone is using
167 * the object as an array. SMJS builtin classes (e.g.
168 * js_RegExpClass) just return JS_TRUE in this case.
169 * Do the same here. */
174 static const JSClass smjs_globhist_item_class
= {
175 "global_history_item",
176 JSCLASS_HAS_PRIVATE
, /* struct global_history_item * */
177 JS_PropertyStub
, JS_PropertyStub
,
178 smjs_globhist_item_get_property
, smjs_globhist_item_set_property
,
179 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
,
180 smjs_globhist_item_finalize
,
184 smjs_get_globhist_item_object(struct global_history_item
*history_item
)
188 jsobj
= JS_NewObject(smjs_ctx
, (JSClass
*) &smjs_globhist_item_class
,
191 || JS_TRUE
!= JS_DefineProperties(smjs_ctx
, jsobj
,
192 (JSPropertySpec
*) smjs_globhist_item_props
)
193 || JS_TRUE
!= JS_SetPrivate(smjs_ctx
, jsobj
, history_item
)) /* to @smjs_globhist_item_class */
196 object_lock(history_item
);
202 /* @smjs_globhist_class.getProperty */
204 smjs_globhist_get_property(JSContext
*ctx
, JSObject
*obj
, jsid id
, jsval
*vp
)
207 unsigned char *uri_string
;
208 struct global_history_item
*history_item
;
211 if (!JS_IdToValue(ctx
, id
, &tmp
))
214 uri_string
= JS_EncodeString(ctx
, JS_ValueToString(ctx
, tmp
));
215 if (!uri_string
) goto ret_null
;
217 history_item
= get_global_history_item(uri_string
);
218 if (!history_item
) goto ret_null
;
220 jsobj
= smjs_get_globhist_item_object(history_item
);
221 if (!jsobj
) goto ret_null
;
223 *vp
= OBJECT_TO_JSVAL(jsobj
);
233 static const JSClass smjs_globhist_class
= {
235 JS_PropertyStub
, JS_PropertyStub
,
236 smjs_globhist_get_property
, JS_StrictPropertyStub
,
237 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, JS_FinalizeStub
,
241 smjs_get_globhist_object(void)
245 globhist
= JS_NewObject(smjs_ctx
, (JSClass
*) &smjs_globhist_class
,
247 if (!globhist
) return NULL
;
253 smjs_init_globhist_interface(void)
256 struct JSObject
*globhist
;
258 if (!smjs_ctx
|| !smjs_elinks_object
)
261 globhist
= smjs_get_globhist_object();
262 if (!globhist
) return;
264 val
= OBJECT_TO_JSVAL(globhist
);
266 JS_SetProperty(smjs_ctx
, smjs_elinks_object
, "globhist", &val
);