1 /* Exports struct cache_entry to the world of ECMAScript */
9 #include "cache/cache.h"
10 #include "ecmascript/spidermonkey/util.h"
11 #include "protocol/uri.h"
12 #include "scripting/smjs/cache_object.h"
13 #include "scripting/smjs/core.h"
14 #include "util/error.h"
15 #include "util/memory.h"
17 static const JSClass cache_entry_class
; /* defined below */
19 /* Tinyids of properties. Use negative values to distinguish these
20 * from array indexes (even though this object has no array elements).
21 * ECMAScript code should not use these directly as in cache_entry[-1];
22 * future versions of ELinks may change the numbers. */
23 enum cache_entry_prop
{
24 CACHE_ENTRY_CONTENT
= -1,
25 CACHE_ENTRY_TYPE
= -2,
26 CACHE_ENTRY_LENGTH
= -3,
27 CACHE_ENTRY_HEAD
= -4,
31 static const JSPropertySpec cache_entry_props
[] = {
32 { "content", CACHE_ENTRY_CONTENT
, JSPROP_ENUMERATE
},
33 { "type", CACHE_ENTRY_TYPE
, JSPROP_ENUMERATE
},
34 { "length", CACHE_ENTRY_LENGTH
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
35 { "head", CACHE_ENTRY_HEAD
, JSPROP_ENUMERATE
},
36 { "uri", CACHE_ENTRY_URI
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
40 /* @cache_entry_class.getProperty */
42 cache_entry_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
)
44 struct cache_entry
*cached
;
46 /* This can be called if @obj if not itself an instance of the
47 * appropriate class but has one in its prototype chain. Fail
49 if (!JS_InstanceOf(ctx
, obj
, (JSClass
*) &cache_entry_class
, NULL
))
52 cached
= JS_GetInstancePrivate(ctx
, obj
,
53 (JSClass
*) &cache_entry_class
, NULL
);
55 if (!cache_entry_is_valid(cached
)) return JS_FALSE
;
57 undef_to_jsval(ctx
, vp
);
59 if (!JSVAL_IS_INT(id
))
62 switch (JSVAL_TO_INT(id
)) {
63 case CACHE_ENTRY_CONTENT
: {
64 struct fragment
*fragment
= get_cache_fragment(cached
);
68 *vp
= STRING_TO_JSVAL(JS_NewStringCopyN(smjs_ctx
,
74 case CACHE_ENTRY_TYPE
:
75 *vp
= STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx
,
76 cached
->content_type
));
79 case CACHE_ENTRY_HEAD
:
80 *vp
= STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx
,
84 case CACHE_ENTRY_LENGTH
:
85 *vp
= INT_TO_JSVAL(cached
->length
);
89 *vp
= STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx
,
90 struri(cached
->uri
)));
94 /* Unrecognized integer property ID; someone is using
95 * the object as an array. SMJS builtin classes (e.g.
96 * js_RegExpClass) just return JS_TRUE in this case
97 * and leave *@vp unchanged. Do the same here.
98 * (Actually not quite the same, as we already used
99 * @undef_to_jsval.) */
104 /* @cache_entry_class.setProperty */
106 cache_entry_set_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
)
108 struct cache_entry
*cached
;
110 /* This can be called if @obj if not itself an instance of the
111 * appropriate class but has one in its prototype chain. Fail
113 if (!JS_InstanceOf(ctx
, obj
, (JSClass
*) &cache_entry_class
, NULL
))
116 cached
= JS_GetInstancePrivate(ctx
, obj
,
117 (JSClass
*) &cache_entry_class
, NULL
);
119 if (!cache_entry_is_valid(cached
)) return JS_FALSE
;
121 if (!JSVAL_IS_INT(id
))
124 switch (JSVAL_TO_INT(id
)) {
125 case CACHE_ENTRY_CONTENT
: {
126 JSString
*jsstr
= JS_ValueToString(smjs_ctx
, *vp
);
127 unsigned char *str
= JS_GetStringBytes(jsstr
);
128 size_t len
= JS_GetStringLength(jsstr
);
130 add_fragment(cached
, 0, str
, len
);
131 normalize_cache_entry(cached
, len
);
135 case CACHE_ENTRY_TYPE
: {
136 JSString
*jsstr
= JS_ValueToString(smjs_ctx
, *vp
);
137 unsigned char *str
= JS_GetStringBytes(jsstr
);
139 mem_free_set(&cached
->content_type
, stracpy(str
));
143 case CACHE_ENTRY_HEAD
: {
144 JSString
*jsstr
= JS_ValueToString(smjs_ctx
, *vp
);
145 unsigned char *str
= JS_GetStringBytes(jsstr
);
147 mem_free_set(&cached
->head
, stracpy(str
));
152 /* Unrecognized integer property ID; someone is using
153 * the object as an array. SMJS builtin classes (e.g.
154 * js_RegExpClass) just return JS_TRUE in this case.
155 * Do the same here. */
160 /* @cache_entry_class.finalize */
162 cache_entry_finalize(JSContext
*ctx
, JSObject
*obj
)
164 struct cache_entry
*cached
;
166 assert(JS_InstanceOf(ctx
, obj
, (JSClass
*) &cache_entry_class
, NULL
));
167 if_assert_failed
return;
169 cached
= JS_GetInstancePrivate(ctx
, obj
,
170 (JSClass
*) &cache_entry_class
, NULL
);
174 object_unlock(cached
);
177 static const JSClass cache_entry_class
= {
179 JSCLASS_HAS_PRIVATE
, /* struct cache_entry * */
180 JS_PropertyStub
, JS_PropertyStub
,
181 cache_entry_get_property
, cache_entry_set_property
,
182 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, cache_entry_finalize
186 smjs_get_cache_entry_object(struct cache_entry
*cached
)
188 JSObject
*cache_entry_object
;
192 cache_entry_object
= JS_NewObject(smjs_ctx
,
193 (JSClass
*) &cache_entry_class
,
196 if (!cache_entry_object
) return NULL
;
198 if (JS_FALSE
== JS_SetPrivate(smjs_ctx
, cache_entry_object
, cached
)) /* to @cache_entry_class */
203 if (JS_FALSE
== JS_DefineProperties(smjs_ctx
, cache_entry_object
,
204 (JSPropertySpec
*) cache_entry_props
))
207 return cache_entry_object
;