#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "JavaScript_Env.h"
#include "PJS_Context.h"
#include "PJS_Property.h"
#include "PJS_Class.h"
#include "PJS_Types.h"
#include "PJS_Common.h"
void PJS_free_property(PJS_Property *pfunc) {
dSP;
if (pfunc == NULL) {
return;
}
if (pfunc->getter != NULL) {
SvREFCNT_dec(pfunc->getter);
}
if (pfunc->setter != NULL) {
SvREFCNT_dec(pfunc->setter);
}
Safefree(pfunc);
}
void PJS_free_JSPropertySpec(JSPropertySpec *ps_list) {
dSP;
JSPropertySpec *ps;
if (ps_list == NULL) {
return;
}
for (ps = ps_list; ps->name; ps++) {
Safefree(ps->name);
}
Safefree(ps_list);
}
JSBool PJS_invoke_perl_property_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) {
dSP;
PJS_Context *pcx;
PJS_Class *pcls;
PJS_Property *pprop;
SV *caller;
char *name;
jsint slot;
U8 invocation_mode;
if (!JSVAL_IS_INT(id)) {
return JS_TRUE;
}
if((pcx = PJS_GET_CONTEXT(cx)) == NULL) {
JS_ReportError(cx, "Can't find context %d", cx);
return JS_FALSE;
}
if (JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj)) == JSTYPE_OBJECT) {
/* Called as instsance */
JSClass *clasp = PJS_GET_CLASS(cx, obj);
name = (char *) clasp->name;
invocation_mode = 1;
}
else {
/* Called as static */
JSFunction *parent_jfunc = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj));
if (parent_jfunc == NULL) {
JS_ReportError(cx, "Failed to extract class for static property getter");
return JS_FALSE;
}
name = (char *) JS_GetFunctionName(parent_jfunc);
invocation_mode = 0;
}
if ((pcls = PJS_GetClassByName(pcx, name)) == NULL) {
JS_ReportError(cx, "Can't find class '%s'", name);
return JS_FALSE;
}
slot = JSVAL_TO_INT(id);
if ((pprop = PJS_get_property_by_id(pcls, (int8) slot)) == NULL) {
JS_ReportError(cx, "Can't find property handler");
return JS_FALSE;
}
if (pprop->getter == NULL) {
JS_ReportError(cx, "Property is write-only");
return JS_FALSE;
}
if (invocation_mode) {
caller = (SV *) JS_GetPrivate(cx, obj);
}
else {
caller = newSVpv(pcls->pkg, 0);
}
if (perl_call_sv_with_jsvals(cx, obj, pprop->getter,
caller, 0, NULL, vp) < 0) {
return JS_FALSE;
}
return JS_TRUE;
}
JSBool PJS_invoke_perl_property_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) {
dSP;
PJS_Context *pcx;
PJS_Class *pcls;
PJS_Property *pprop;
SV *caller;
char *name;
jsint slot;
U8 invocation_mode;
if (!JSVAL_IS_INT(id)) {
return JS_TRUE;
}
if((pcx = PJS_GET_CONTEXT(cx)) == NULL) {
JS_ReportError(cx, "Can't find context %d", cx);
return JS_FALSE;
}
if (JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj)) == JSTYPE_OBJECT) {
/* Called as instsance */
JSClass *clasp = PJS_GET_CLASS(cx, obj);
name = (char *) clasp->name;
invocation_mode = 1;
}
else {
/* Called as static */
JSFunction *parent_jfunc = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj));
if (parent_jfunc == NULL) {
JS_ReportError(cx, "Failed to extract class for static property getter");
return JS_FALSE;
}
name = (char *) JS_GetFunctionName(parent_jfunc);
invocation_mode = 0;
}
if ((pcls = PJS_GetClassByName(pcx, name)) == NULL) {
JS_ReportError(cx, "Can't find class '%s'", name);
return JS_FALSE;
}
slot = JSVAL_TO_INT(id);
if ((pprop = PJS_get_property_by_id(pcls, (int8) slot)) == NULL) {
JS_ReportError(cx, "Can't find property handler");
return JS_FALSE;
}
if (pprop->setter == NULL) {
JS_ReportError(cx, "Property is read-only");
return JS_FALSE;
}
if (invocation_mode) {
caller = (SV *) JS_GetPrivate(cx, obj);
}
else {
caller = newSVpv(pcls->pkg, 0);
}
if (perl_call_sv_with_jsvals(cx, obj, pprop->setter,
caller, 1, vp, NULL) < 0) {
return JS_FALSE;
}
return JS_TRUE;
}