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) || JSVAL_IS_STRING(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; } if (invocation_mode) { caller = (SV *) JS_GetPrivate(cx, obj); } else { caller = newSVpv(pcls->pkg, 0); } if (JSVAL_IS_INT(id)) { slot = JSVAL_TO_INT(id); if ((pprop = PJS_get_property_by_id(pcls, (int8) slot)) == NULL) { if (SvTRUE(pcls->property_getter)) { if (perl_call_sv_with_jsvals(cx, obj, pcls->property_getter, caller, 1, &id, vp) < 0) { return JS_FALSE; } return JS_TRUE; } 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 (perl_call_sv_with_jsvals(cx, obj, pprop->getter, caller, 0, NULL, vp) < 0) { return JS_FALSE; } } else if (JSVAL_IS_STRING(id) && SvTRUE(pcls->property_getter)) { SV *sv = sv_newmortal(); #ifdef JS_C_STRINGS_ARE_UTF8 char *tmp = JS_smprintf("%hs", JS_GetStringChars(JSVAL_TO_STRING(id))); sv_setpv(sv, tmp); SvUTF8_on(sv); free(tmp); #else sv_setpv(sv, JS_GetStringBytes(JSVAL_TO_STRING(id))); #endif if (PJS_get_method_by_name(pcls, SvPV_nolen(sv))) { return JS_TRUE; } if (perl_call_sv_with_jsvals(cx, obj, pcls->property_getter, caller, 1, &id, vp) < 0) { return JS_FALSE; } } return JS_TRUE; }
JSBool PJS_invoke_perl_object_method(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { PJS_Context *pcx; PJS_Class *pcls; PJS_Function *pfunc; JSFunction *jfunc = PJS_FUNC_SELF; SV *caller; char *name; U8 invocation_mode; 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))) { JS_ReportError(cx, "Can't find class '%s'", name); return JS_FALSE; } name = (char *) JS_GetFunctionName(jfunc); if((pfunc = PJS_get_method_by_name(pcls, name)) == NULL) { JS_ReportError(cx, "Can't find method '%s' in '%s'", name, pcls->clasp->name); return JS_FALSE; } if (invocation_mode) { caller = (SV *) JS_GetPrivate(cx, obj); } else { caller = newSVpv(pcls->pkg, 0); } /* XXX: the original invocation here has slightly different retrun value handling. if the returned value is reference same as priv, don't return it. While the case is not covered by the tets */ if (perl_call_sv_with_jsvals(cx, obj, pfunc->callback, caller, argc, argv, rval) < 0) { return JS_FALSE; } return JS_TRUE; }