static mrb_value mrb_js_obj_method_missing(mrb_state *mrb, mrb_value self) { NPP npp = MRB_UD_NPP(mrb); mrb_value name_sym, *args; int len; mrb_get_args(mrb, "o*", &name_sym, &args, &len); if (mrb_type(name_sym) != MRB_TT_SYMBOL){ return mrb_nil_value(); } bool success = true; NPVariant empty; NULL_TO_NPVARIANT(empty); std::vector< NPVariant > var_args(len, empty); for (int i=0; i<len; i++){ if (!convert_mrb_to_js(mrb, args[i], npp, &var_args[i])){ success = false; break; } } mrb_value ret = mrb_nil_value(); if (success){ int name_len; const char *name_char = mrb_sym2name_len(mrb, SYM2ID(name_sym), &name_len); std::string name(name_char, name_len); NPIdentifier name_id = NPN_GetStringIdentifier(name.c_str()); NPObject *obj = (NPObject *)DATA_PTR(self); if (NPN_HasMethod(npp, obj, name_id)){ NPVariant result; NPN_Invoke(npp, obj, name_id, &var_args[0], len, &result); convert_js_to_mrb(npp, result, mrb, &ret); }else if (NPN_HasProperty(npp, obj, name_id)){ NPVariant result; NPN_GetProperty(npp, obj, name_id, &result); convert_js_to_mrb(npp, result, mrb, &ret); }else if (name.size() > 1 && name[name.size() - 1] == '=' && var_args.size() == 1){ name.resize(name.size() - 1); name_id = NPN_GetStringIdentifier(name.c_str()); if (NPN_HasProperty(npp, obj, name_id)){ NPN_SetProperty(npp, obj, name_id, &var_args[0]); } } } for (int i=0; i<len; i++){ NPN_ReleaseVariantValue(&var_args[i]); } return ret; }
int QtSignalForwarder::qt_metacall(QMetaObject::Call call, int index, void **args) { // no support for QObject method/properties etc! if (!This || !This->npp || call != QMetaObject::InvokeMetaMethod || !This->qt.object) return index; switch (index) { case -1: { QString msg = *(QString*)args[1]; NPN_Status(This->npp, msg.toLocal8Bit().constData()); } break; default: { QObject *qobject = This->qt.object; if (!domNode) NPN_GetValue(This->npp, NPNVPluginElementNPObject, &domNode); if (!domNode) break; const QMetaObject *metaObject = qobject->metaObject(); if (index < metaOffset(metaObject, MetaMethod)) break; const QMetaMethod method = metaObject->method(index); Q_ASSERT(method.methodType() == QMetaMethod::Signal); QByteArray signalSignature = method.signature(); QByteArray scriptFunction = signalSignature.left(signalSignature.indexOf('(')); NPIdentifier id = NPN_GetStringIdentifier(scriptFunction.constData()); if (NPN_HasMethod(This->npp, domNode, id)) { QList<QByteArray> parameterTypes = method.parameterTypes(); QVector<NPVariant> parameters; NPVariant result; bool error = false; for (int p = 0; p < parameterTypes.count(); ++p) { QVariant::Type type = QVariant::nameToType(parameterTypes.at(p)); if (type == QVariant::Invalid) { NPN_SetException(domNode, QByteArray("Unsupported parameter type in ") + scriptFunction); error = true; break; } QVariant qvar(type, args[p + 1]); NPVariant npvar = NPVariant::fromQVariant(This, qvar); if (npvar.type == NPVariant::Null || npvar.type == NPVariant::Void) { NPN_SetException(domNode, QByteArray("Unsupported parameter value in ") + scriptFunction); error =true; break; } parameters += npvar; } if (error) break; NPError nperror = NPN_Invoke(This->npp, domNode, id, parameters.constData(), parameters.count(), &result); if (nperror != NPERR_NO_ERROR && false) { // disabled, as NPN_Invoke seems to always return GENERICERROR NPN_SetException(domNode, QByteArray("Error invoking event handler ") + scriptFunction); } // ### TODO: update return value (args[0]) (out-parameters not supported anyway) NPN_ReleaseVariantValue(&result); } } break; } return index; }