JSBool JavaObject::getProperty(JSContext* ctx, JSObject* obj, jsid id, jsval* rval) { Debug::log(Debug::Spam) << "JavaObject::getProperty obj=" << obj << Debug::flush; SessionData* data = JavaObject::getSessionData(ctx, obj); if (!data) { // TODO: replace the frame with an error page instead? *rval = JSVAL_VOID; return JS_TRUE; } int objectRef = JavaObject::getObjectId(ctx, obj); if (JSID_IS_STRING(id)) { JSString* str = JSID_TO_STRING(id); if ((JS_GetStringEncodingLength(ctx, str) == 8) && !strncmp("toString", JS_EncodeString(ctx, str), 8)) { *rval = data->getToStringTearOff(); return JS_TRUE; } if ((JS_GetStringEncodingLength(ctx, str) == 2) && !strncmp("id", JS_EncodeString(ctx, str), 2)) { *rval = INT_TO_JSVAL(objectRef); return JS_TRUE; } if ((JS_GetStringEncodingLength(ctx, str) == 16) && !strncmp("__noSuchMethod__", JS_EncodeString(ctx, str), 16)) { // Avoid error spew if we are disconnected *rval = JSVAL_VOID; return JS_TRUE; } Debug::log(Debug::Error) << "Getting unexpected string property " << dumpJsVal(ctx, id) << Debug::flush; // TODO: throw a better exception here return JS_FALSE; } if (!JSID_IS_INT(id)) { Debug::log(Debug::Error) << "Getting non-int/non-string property " << dumpJsVal(ctx, id) << Debug::flush; // TODO: throw a better exception here return JS_FALSE; } int dispId = JSID_TO_INT(id); HostChannel* channel = data->getHostChannel(); SessionHandler* handler = data->getSessionHandler(); Value value = ServerMethods::getProperty(*channel, handler, objectRef, dispId); data->makeJsvalFromValue(*rval, ctx, value); return JS_TRUE; }
void FFSessionHandler::getToStringTearOff(JSContext* ctx) { jsval funcVal; Debug::log(Debug::Debugging) << "Getting function \"__gwt_makeTearOff\"" << Debug::flush; if (!JS_GetProperty(ctx, global, "__gwt_makeTearOff", &funcVal) || funcVal == JSVAL_VOID) { Debug::log(Debug::Error) << "Could not get function \"__gwt_makeTearOff\"" << Debug::flush; return; } jsval jsargs[3] = { JSVAL_NULL, // no proxy INT_TO_JSVAL(InvokeMessage::TOSTRING_DISP_ID), // dispId JSVAL_ZERO // arg count is zero }; if (!JS_CallFunctionValue(ctx, global, funcVal, 3, jsargs, &toStringTearOff)) { jsval exc; if (JS_GetPendingException(ctx, &exc)) { Debug::log(Debug::Error) << "__gwt_makeTearOff(null,0,0) threw exception " << dumpJsVal(ctx, exc) << Debug::flush; } else { Debug::log(Debug::Error) << "Error creating toString tear-off" << Debug::flush; } // TODO(jat): show some crash page and die } }
/** * Called when the JavaObject is invoked as a function. * We ignore the JSObject* argument, which is the 'this' context, which is * usually the window object. The JavaObject instance is in argv[-2]. * * Returns a JS array, with the first element being a boolean indicating that * an exception occured, and the second element is either the return value or * the exception which was thrown. In this case, we always return false and * raise the exception ourselves. */ JSBool JavaObject::call(JSContext* ctx, JSObject*, uintN argc, jsval* argv, jsval* rval) { // Get the JavaObject called as a function JSObject* obj = JSVAL_TO_OBJECT(argv[-2]); if (argc < 2 || !JSVAL_IS_INT(argv[0]) || #ifdef JSVAL_IS_OBJECT !JSVAL_IS_OBJECT(argv[1])) { #else (JSVAL_IS_PRIMITIVE(argv[1]) && !JSVAL_IS_NULL(argv[1]))) { #endif Debug::log(Debug::Error) << "JavaObject::call incorrect arguments" << Debug::flush; return JS_FALSE; } int dispId = JSVAL_TO_INT(argv[0]); if (Debug::level(Debug::Spam)) { Debug::DebugStream& dbg = Debug::log(Debug::Spam) << "JavaObject::call oid=" << JavaObject::getObjectId(ctx, obj) << ",dispId=" << dispId << " ("; for (unsigned i = 2; i < argc; ++i) { if (i > 2) { dbg << ", "; } dbg << dumpJsVal(ctx, argv[i]); } dbg << ")" << Debug::flush; } SessionData* data = JavaObject::getSessionData(ctx, obj); if (!data) { *rval = JSVAL_VOID; return JS_TRUE; } Debug::log(Debug::Spam) << "Data = " << data << Debug::flush; gwt::Value javaThis; if (!JSVAL_IS_NULL(argv[1])) { JSObject* thisObj = JSVAL_TO_OBJECT(argv[1]); if (isJavaObject(ctx, thisObj)) { javaThis.setJavaObject(getObjectId(ctx, thisObj)); } else { data->makeValueFromJsval(javaThis, ctx, argv[1]); } } else { int oid = getObjectId(ctx, obj); javaThis.setJavaObject(oid); } return invokeJava(ctx, data, javaThis, dispId, argc - 2, &argv[2], rval); }