Exemple #1
0
/*
 * call-seq:
 *   call_function_property(name, arguments)
 *
 * Calls this JavaScript object's +name+ method, passing the given
 * arguments.
 *
 * Equivalent to:
 *    proxy[name].native_call(proxy, *arguments)
 */
static VALUE
call_function_property(int argc, VALUE* argv, VALUE self)
{
  RubyLandProxy* proxy;
  Data_Get_Struct(self, RubyLandProxy, proxy);
  JSContext * context = johnson_get_current_context(proxy->runtime);

  if (argc < 1)
    rb_raise(rb_eArgError, "Function name required");

  PREPARE_RUBY_JROOTS(context, 2);
  
  jsval proxy_value;
  JCHECK(get_jsval_for_proxy(proxy, &proxy_value));
  JROOT(proxy_value);

  jsval function;

  VALUE name = argv[0];
  CALL_RUBY_WRAPPER(rb_string_value_cstr, &name);
  
  JCHECK(JS_GetProperty(context,
    JSVAL_TO_OBJECT(proxy_value), StringValueCStr(name), &function));

  JROOT(function);

  // should never be anything but a function
  if (!JS_ObjectIsFunction(context, function))
    JERROR("Specified property \"%s\" isn't a function.", StringValueCStr(name));

  REMOVE_JROOTS;

  return call_js_function_value(proxy->runtime, proxy_value, function, argc - 1, &(argv[1]));
}
JSBool
WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
{
  if (JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(v))) {
    return WrapFunction(cx, parent, JSVAL_TO_OBJECT(v), vp);
  }

  JSObject *wrapperObj =
    JS_NewObjectWithGivenProto(cx, &COWClass.base, NULL, parent);
  if (!wrapperObj) {
    return JS_FALSE;
  }

  *vp = OBJECT_TO_JSVAL(wrapperObj);

  jsval exposedProps = JSVAL_VOID;
  JSAutoTempValueRooter tvr(cx, 1, &exposedProps);

  if (!GetExposedProperties(cx, JSVAL_TO_OBJECT(v), &exposedProps)) {
    return JS_FALSE;
  }

  if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) ||
      !JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot,
                          JSVAL_ZERO) ||
      !JS_SetReservedSlot(cx, wrapperObj, sExposedPropsSlot, exposedProps)) {
    return JS_FALSE;
  }

  return JS_TRUE;
}
Exemple #3
0
std::string ValueWriter::typeAsString() {
    if (_value.isNull())
        return "null";
    if (_value.isUndefined())
        return "undefined";
    if (_value.isString())
        return "string";
    if (JS_IsArrayObject(_context, _value))
        return "array";
    if (_value.isBoolean())
        return "boolean";
    if (_value.isNumber())
        return "number";

    if (_value.isObject()) {
        JS::RootedObject obj(_context, _value.toObjectOrNull());
        if (JS_IsArrayObject(_context, obj))
            return "array";
        if (JS_ObjectIsDate(_context, obj))
            return "date";
        if (JS_ObjectIsFunction(_context, obj))
            return "function";

        return ObjectWrapper(_context, _value).getClassName();
    }

    uasserted(ErrorCodes::BadValue, "unable to get type");
}
Exemple #4
0
int ValueWriter::type() {
    if (_value.isNull())
        return jstNULL;
    if (_value.isUndefined())
        return Undefined;
    if (_value.isString())
        return String;
    if (JS_IsArrayObject(_context, _value))
        return Array;
    if (_value.isBoolean())
        return Bool;

    // We could do something more sophisticated here by checking to see if we
    // round trip through int32_t, int64_t and double and picking a type that
    // way, for now just always come back as double for numbers though (it's
    // what we did for v8)
    if (_value.isNumber())
        return NumberDouble;

    if (_value.isObject()) {
        JS::RootedObject obj(_context, _value.toObjectOrNull());
        if (JS_ObjectIsDate(_context, obj))
            return Date;
        if (JS_ObjectIsFunction(_context, obj))
            return Code;

        return Object;
    }

    uasserted(ErrorCodes::BadValue, "unable to get type");
}
Exemple #5
0
JSBool 
js_addsubprovider(JSContext *cx, JSObject *obj, uintN argc, 
		  jsval *argv, jsval *rval)
{
  js_subprovider_t *sp;
  js_plugin_t *jsp = JS_GetPrivate(cx, obj);

  if(!JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[0]))) {
    JS_ReportError(cx, "Argument is not a function");
    return JS_FALSE;
  }

  sp = calloc(1, sizeof(js_subprovider_t));

  sp->super.sp_query        = js_sub_query;
  sp->super.sp_retain       = js_sub_retain;

  sp->sp_title = prop_create_root(NULL);
  prop_set_string(sp->sp_title, jsp->jsp_id);

  subtitle_provider_register(&sp->super,
                             jsp->jsp_id, sp->sp_title,
                             0, "plugin", 1, 1);

  sp->sp_jsp = jsp;
  LIST_INSERT_HEAD(&jsp->jsp_subproviders, sp, sp_plugin_link);

  sp->sp_func = argv[0];
  atomic_set(&sp->sp_refcnt, 1);
  JS_AddNamedRoot(cx, &sp->sp_func, "subprovider");

  *rval = JSVAL_VOID;
  return JS_TRUE;
}
Exemple #6
0
static JSBool 
js_item_onEvent(JSContext *cx, JSObject *obj,
		uintN argc, jsval *argv, jsval *rval)
{
  js_item_t *ji = JS_GetPrivate(cx, obj);

  if(!JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[1]))) {
    JS_ReportError(cx, "Argument is not a function");
    return JS_FALSE;
  }

  if(ji->ji_eventsub == NULL) {
    ji->ji_eventsub = 
      prop_subscribe(PROP_SUB_TRACK_DESTROY,
		     PROP_TAG_CALLBACK, js_item_eventsub, ji,
		     PROP_TAG_ROOT, ji->ji_root,
		     PROP_TAG_COURIER, ji->ji_model->jm_pc,
		     NULL);
    ji->ji_model->jm_subs++;
    ji->ji_this = OBJECT_TO_JSVAL(obj);
    JS_AddNamedRoot(cx, &ji->ji_this, "item_this");
  }

  js_event_handler_create(cx, &ji->ji_event_handlers,
			  JSVAL_IS_STRING(argv[0]) ?
			  JS_GetStringBytes(JS_ValueToString(cx, argv[0])) :
			  NULL,
			  argv[1]);
  
  *rval = JSVAL_VOID;
  return JS_TRUE;
}
Exemple #7
0
/* Mimick the behaviour exposed by standard Error objects
   (http://mxr.mozilla.org/mozilla-central/source/js/src/jsexn.cpp#554)
*/
static char*
jsvalue_to_string(JSContext* cx, jsval val, gboolean* is_string)
{
    char* value = NULL;
    JSString* value_str = NULL;

    if (JSVAL_IS_PRIMITIVE(val)) {
      value_str = JS_ValueToSource(cx, val);
    } else {
      JSObject *obj = JSVAL_TO_OBJECT(val);

      if (JS_ObjectIsFunction(cx, obj)) {
	JSFunction *fn = JS_ValueToFunction(cx, val);
	value_str = JS_GetFunctionId(fn);

	if (!value_str)
	  value = g_strdup("[unknown function]");
      } else {
	value = g_strdup_printf("[object %s]", JS_GetClass(cx, obj)->name);
      }
    }

    if (!value && value_str)
      value = gjs_value_debug_string(cx, val);

    if (is_string)
        *is_string = JSVAL_IS_STRING(val);

    return value;
}
Exemple #8
0
    JSThreadConfig(JSContext* cx, JS::CallArgs args)
        : _started(false), _done(false), _sharedData(new SharedData()) {
        auto scope = getScope(cx);

        uassert(ErrorCodes::JSInterpreterFailure, "need at least one argument", args.length() > 0);
        uassert(ErrorCodes::JSInterpreterFailure,
                "first argument must be a function",
                args.get(0).isObject() && JS_ObjectIsFunction(cx, args.get(0).toObjectOrNull()));

        BSONObjBuilder b;
        for (unsigned i = 0; i < args.length(); ++i) {
            // 10 decimal digits for a 32 bit unsigned, then 1 for the null
            char buf[11];
            std::sprintf(buf, "%i", i);

            ValueWriter(cx, args.get(i)).writeThis(&b, buf);
        }

        _sharedData->_args = b.obj();

        _sharedData->_stack = currentJSStackToString(cx);

        if (!scope->getParentStack().empty()) {
            _sharedData->_stack = _sharedData->_stack + scope->getParentStack();
        }
    }
Exemple #9
0
static inline void build_frame(JSContext *cx, JSObject *target, unsigned argc, jsval *vp, void (*next)(view_animation *, anim_frame *, unsigned int, unsigned int)) {
	LOGFN("build_frame");
	
	JSObject *thiz = JSVAL_TO_OBJECT(JS_THIS(cx, vp));
	view_animation *anim = (view_animation*)JS_GetPrivate(thiz);
	anim_frame *frame = anim_frame_get();

	// TODO: what if these defaults change? it probably won't...
	int32_t duration = 500;
	int32_t transition = 0;
	if (JS_ObjectIsFunction(cx, target)) {
		duration = 0;
		build_func_frame(frame, target);
	} else {
		build_style_frame(frame, target);
	}

	jsval *vals = JS_ARGV(cx, vp);
	if (argc > 1) {
		duration = JSValToInt32(cx, vals[1], duration);
		if (argc > 2) {
			transition = JSValToInt32(cx, vals[2], transition);
		}
	}

	next(anim, frame, duration, transition);

	LOGFN("end build_frame");
}
Exemple #10
0
static js_setting_t *
jss_create(JSContext *cx, JSObject *obj, const char *id, jsval *rval,
	   JSObject *func, js_setting_group_t *jsg, int persistent)
{
  if(jsg->jsg_root == NULL) {
    JS_ReportError(cx, "Settings group has been destroyed");
    return NULL;
  }

  if(!JS_ObjectIsFunction(cx, func)) {
    JS_ReportError(cx, "Callback is not a function");
    return NULL;
  }

  js_setting_t *jss = calloc(1, sizeof(js_setting_t));
  jss->jss_cx = cx;
  jss->jss_refcount = 1;
  jss->jss_jsg = jsg;
  jss->jss_key = persistent && jsg->jsg_kv_url ? strdup(id) : NULL;
  LIST_INSERT_HEAD(&jsg->jsg_settings, jss, jss_link);
  atomic_add(&jsg->jsg_refcount, 1);
  JS_AddNamedRoot(cx, &jss->jss_obj, "jss");
  jss->jss_obj = OBJECT_TO_JSVAL(JS_DefineObject(cx, obj, id,
						 &setting_class, NULL, 0));
  *rval = jss->jss_obj;
  JS_SetPrivate(cx, JSVAL_TO_OBJECT(jss->jss_obj), jss);

  jsval v = OBJECT_TO_JSVAL(func);
  JS_SetProperty(cx, JSVAL_TO_OBJECT(jss->jss_obj), "callback", &v);
  return jss;
}
static void _gjs_builder_connect_func (GtkBuilder *builder,
                                       GObject *object,
                                       const gchar *signal_name,
                                       const gchar *handler_name,
                                       GObject *connect_object,
                                       GConnectFlags flags,
                                       gpointer user_data)
{
    builder_ud *priv = (builder_ud *)user_data;
    JSContext *ctx = priv->ctx;
    JSObject *obj = priv->obj;
    GClosure *closure;
    JSObject *callable;
    builder_cd *cd;
    closure_data *c;
    jsval func;

    if (!gjs_object_get_property (ctx, obj, handler_name, &func))
        return;

    if (!JSVAL_IS_OBJECT(func))
        return;

    callable = JSVAL_TO_OBJECT (func);
    if (!JS_ObjectIsFunction(ctx, callable))
        return;

    /* Protect from garbage collection. */
    cd = g_object_get_data (G_OBJECT (builder), GJS_BUILDER_CLOSURE_KEY);
    if (!cd) {
        cd = g_new0 (builder_cd, 1);
        cd->context = ctx;
        cd->closures = NULL;
        g_object_set_data_full (G_OBJECT (builder),
                                GJS_BUILDER_CLOSURE_KEY,
                                cd,
                                (GDestroyNotify) _builder_cd_free);
    }

    g_assert (cd->context == ctx);

    c = g_new0 (closure_data, 1);
    c->jsobj = callable;
    cd->closures = g_slist_prepend (cd->closures, c);
    JS_AddObjectRoot (ctx, &c->jsobj);

    closure = gjs_closure_new_for_signal (ctx,
                                          callable,
                                          "signal handler (GtkBuilder)",
                                          0);
    if (connect_object != NULL)
        g_object_watch_closure (connect_object, closure);

    c->object = g_object_ref (object);
    c->handler_id = g_signal_connect_closure (object, signal_name, closure, FALSE);
}
Exemple #12
0
JSBool
add_prop(JSContext* jscx, JSObject* jsobj, jsval key, jsval* rval)
{
    JSObject* obj = NULL;

    if(JSVAL_IS_NULL(*rval) || !JSVAL_IS_OBJECT(*rval)) return JS_TRUE;

    obj = JSVAL_TO_OBJECT(*rval);
    if(JS_ObjectIsFunction(jscx, obj)) return set_prop(jscx, jsobj, key, rval);
    return JS_TRUE;
}
Exemple #13
0
void MozJSImplScope::_MozJSCreateFunction(const char* raw,
                                          ScriptingFunction functionNumber,
                                          JS::MutableHandleValue fun) {
    std::string code = str::stream() << "_funcs" << functionNumber << " = "
                                     << parseJSFunctionOrExpression(_context, StringData(raw));

    JS::CompileOptions co(_context);
    setCompileOptions(&co);

    _checkErrorState(JS::Evaluate(_context, _global, co, code.c_str(), code.length(), fun));
    uassert(10232,
            "not a function",
            fun.isObject() && JS_ObjectIsFunction(_context, fun.toObjectOrNull()));
}
Exemple #14
0
static void
GetMethodInfo(JSContext *cx,
              jsval *vp,
              const char **ifaceName,
              const char **memberName)
{
    JSObject *funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
    NS_ASSERTION(JS_ObjectIsFunction(cx, funobj),
                 "JSFastNative callee should be Function object");
    JSString *str = JS_GetFunctionId((JSFunction *) JS_GetPrivate(cx, funobj));
    jsval methodId = str ? STRING_TO_JSVAL(str) : JSVAL_NULL;

    GetMemberInfo(JSVAL_TO_OBJECT(vp[1]), methodId, ifaceName, memberName);
}
XPCDispJSPropertyInfo::XPCDispJSPropertyInfo(JSContext* cx, PRUint32 memid,
        JSObject* obj, jsval val) :
    mPropertyType(INVALID), mMemID(memid)
{
    PRUint32 len;
    jschar * chars = xpc_JSString2String(cx, val, &len);
    if(!chars)
        return;

    mName = nsString(reinterpret_cast<const PRUnichar *>(chars), len);
    JSBool found;
    uintN attr;
    // Get the property's attributes, and make sure it's found and enumerable
    if(!JS_GetUCPropertyAttributes(cx, obj, chars, len, &attr, &found) ||
            !found || (attr & JSPROP_ENUMERATE) == 0)
        return;

    // Retrieve the property
    if(!chars || !JS_GetUCProperty(cx, obj, chars, len, &mProperty) ||
            JSVAL_IS_NULL(mProperty))
        return;

    // If this is a function
    if(JSVAL_IS_OBJECT(mProperty) &&
            JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(mProperty)))
    {
        mPropertyType = FUNCTION;
        JSObject * funcObj = JSVAL_TO_OBJECT(mProperty);
        JSIdArray * funcObjArray = JS_Enumerate(cx, funcObj);
        if(funcObjArray)
        {
            mParamCount = funcObjArray->length;
        }
    }
    else // It's a property
    {
        mParamCount = 0;
        if((attr & JSPROP_READONLY) != 0)
        {
            mPropertyType = READONLY_PROPERTY;
        }
        else
        {
            mPropertyType = PROPERTY;
        }
    }
}
js::Function JSInterpreter::evaluateScript(std::string script){
    jsval rval;
    JSBool ok;
    const char *filename = "noname";

    uintN lineno = 0;
    ok = JS_EvaluateScript(cx, global, script.c_str(), script.length(),
                           filename, lineno, &rval);
    if (rval == JSVAL_NULL || rval == JS_FALSE || ok == JS_FALSE){
        throw * new std::runtime_error("Could not evaluate script");
    }

    JSObject *obj;
    JS_ValueToObject(cx, rval, &obj);
    JSBool func = JS_ObjectIsFunction(cx, obj);
    //todo guard!
    return js::Function(obj);
}
Exemple #17
0
static JSBool 
js_item_onEvent(JSContext *cx, JSObject *obj,
		uintN argc, jsval *argv, jsval *rval)
{
  js_item_t *ji = JS_GetPrivate(cx, obj);

  if(!JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[1]))) {
    JS_ReportError(cx, "Argument is not a function");
    return JS_FALSE;
  }

  js_event_handler_create(cx, &ji->ji_event_handlers,
			  JSVAL_IS_STRING(argv[0]) ?
			  JS_GetStringBytes(JS_ValueToString(cx, argv[0])) :
			  NULL,
			  argv[1]);
  
  *rval = JSVAL_VOID;
  return JS_TRUE;
}
JSBool
XPC_COW_RewrapForContent(JSContext *cx, JSObject *wrapperObj, jsval *vp)
{
  jsval v = *vp;
  if (JSVAL_IS_PRIMITIVE(v)) {
    return JS_TRUE;
  }

  JSObject *obj = GetWrappedJSObject(cx, JSVAL_TO_OBJECT(v));
  if (!obj) {
    *vp = JSVAL_NULL;
    return JS_TRUE;
  }

  if (JS_ObjectIsFunction(cx, obj)) {
    return XPC_COW_WrapFunction(cx, wrapperObj, obj, vp);
  }

  return XPC_COW_WrapObject(cx, JS_GetScopeChain(cx), OBJECT_TO_JSVAL(obj),
                            vp);
}
void DBQueryInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) {
    *resolvedp = false;

    IdWrapper wid(cx, id);

    // We only use this for index access
    if (!wid.isInt()) {
        return;
    }

    JS::RootedObject parent(cx);
    if (!JS_GetPrototype(cx, obj, &parent))
        uasserted(ErrorCodes::InternalError, "Couldn't get prototype");

    ObjectWrapper parentWrapper(cx, parent);

    JS::RootedValue arrayAccess(cx);
    parentWrapper.getValue(InternedString::arrayAccess, &arrayAccess);

    if (arrayAccess.isObject() && JS_ObjectIsFunction(cx, arrayAccess.toObjectOrNull())) {
        JS::AutoValueArray<1> args(cx);

        args[0].setInt32(wid.toInt32());

        JS::RootedValue vp(cx);

        ObjectWrapper(cx, obj).callMethod(arrayAccess, args, &vp);

        if (!vp.isNullOrUndefined()) {
            ObjectWrapper o(cx, obj);

            // Assumes the user won't modify the contents of what DBQuery::arrayAccess returns
            // otherwise we need to install a getter.
            o.defineProperty(id, vp, 0);
        }

        *resolvedp = true;
    }
}
Exemple #20
0
// TODO: This function identification code is broken.  Fix it up to be more robust
//
// See: SERVER-16703 for more info
void MozJSImplScope::_MozJSCreateFunction(const char* raw,
                                          ScriptingFunction functionNumber,
                                          JS::MutableHandleValue fun) {
    std::string code = jsSkipWhiteSpace(raw);
    if (!hasFunctionIdentifier(code)) {
        if (code.find('\n') == std::string::npos && !hasJSReturn(code) &&
            (code.find(';') == std::string::npos || code.find(';') == code.size() - 1)) {
            code = "return " + code;
        }
        code = "function(){ " + code + "}";
    }

    code = str::stream() << "_funcs" << functionNumber << " = " << code;

    JS::CompileOptions co(_context);
    setCompileOptions(&co);

    _checkErrorState(JS::Evaluate(_context, _global, co, code.c_str(), code.length(), fun));
    uassert(10232,
            "not a function",
            fun.isObject() && JS_ObjectIsFunction(_context, fun.toObjectOrNull()));
}
JSBool
XPC_XOW_RewrapIfNeeded(JSContext *cx, JSObject *outerObj, jsval *vp)
{
  // Don't need to wrap primitive values.
  if (JSVAL_IS_PRIMITIVE(*vp)) {
    return JS_TRUE;
  }

  JSObject *obj = JSVAL_TO_OBJECT(*vp);

  if (JS_ObjectIsFunction(cx, obj)) {
    return XPC_XOW_WrapFunction(cx, outerObj, obj, vp);
  }

  XPCWrappedNative *wn = nsnull;
  if (STOBJ_GET_CLASS(obj) == &sXPC_XOW_JSClass.base &&
      STOBJ_GET_PARENT(outerObj) != STOBJ_GET_PARENT(obj)) {
    *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, obj));
  } else if (!(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj))) {
    return JS_TRUE;
  }

  return XPC_XOW_WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp, wn);
}
Exemple #22
0
int
to_erl_from_handler(emonk_buf_t* buf, JSContext* cx, JSObject* obj)
{
    JSObject* func;
    jsval tojson;
    jsval rval;
    
    if(!JS_GetProperty(cx, obj, "toJSON", &tojson))
    {
        return ERROR;
    }
    
    if(!JSVAL_IS_OBJECT(tojson)) return IGNORE;
    func = JSVAL_TO_OBJECT(tojson);
    if(func == NULL) return ERROR;
    if(!JS_ObjectIsFunction(cx, func)) return IGNORE;

    if(!JS_CallFunctionValue(cx, obj, tojson, 0, NULL, &rval))
    {
        return ERROR;
    }
    
    return to_erl_intern(buf, cx, rval);
}
Exemple #23
0
void def_animate_finish(void *a) {
	JSObject *js_anim = (JSObject*)a;
	LOGFN("js_animate_finish");
	JSContext *cx = get_js_context();

	JS_BeginRequest(cx);

	view_animation *anim = (view_animation *)JS_GetPrivate(js_anim);
	JSObject *js_group = (JSObject*)anim->js_group;
	jsval finish_val;
	JS_GetProperty(cx, js_group, "onAnimationFinish", &finish_val);
	if (JSVAL_IS_OBJECT(finish_val)) {
		JSObject *finish = JSVAL_TO_OBJECT(finish_val);
		jsval args[] = {OBJECT_TO_JSVAL(js_anim)};
		if (JS_ObjectIsFunction(cx, finish)) {
			jsval ret;
			JS_CallFunctionValue(cx, js_group, finish_val, 1, args, &ret);
		}
	}

	JS_EndRequest(cx);

	LOGFN("end def_animate_finish");
}
JSBool
RewrapIfNeeded(JSContext *cx, JSObject *outerObj, jsval *vp)
{
  // Don't need to wrap primitive values.
  if (JSVAL_IS_PRIMITIVE(*vp)) {
    return JS_TRUE;
  }

  JSObject *obj = JSVAL_TO_OBJECT(*vp);

  if (JS_ObjectIsFunction(cx, obj)) {
    return WrapFunction(cx, outerObj, obj, vp);
  }

  XPCWrappedNative *wn = nsnull;
  if (obj->getClass() == &XOWClass &&
      outerObj->getParent() != obj->getParent()) {
    *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, obj));
  } else if (!(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj))) {
    return JS_TRUE;
  }

  return WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp, wn);
}
Exemple #25
0
int
to_erl_convert(ErlNifEnv* env, JSContext* cx, JSObject* obj, ERL_NIF_TERM* term)
{
    JSObject* func;
    jsval tojson;
    jsval rval;
    
    if(!JS_GetProperty(cx, obj, "toJSON", &tojson))
    {
        return ERROR;
    }
    
    if(!JSVAL_IS_OBJECT(tojson)) return ERROR;
    func = JSVAL_TO_OBJECT(tojson);
    if(func == NULL) return ERROR;
    if(!JS_ObjectIsFunction(cx, func)) return ERROR;

    if(!JS_CallFunctionValue(cx, obj, tojson, 0, NULL, &rval))
    {
        return ERROR;
    }
    
    return to_erl_intern(env, cx, rval, term);
}
Exemple #26
0
static gboolean
peas_extension_gjs_call (PeasExtensionWrapper *exten,
                         GType                 exten_type,
                         GICallableInfo       *func_info,
                         const gchar          *method_name,
                         GIArgument           *args,
                         GIArgument           *retval)
{
  PeasExtensionGjs *gexten = PEAS_EXTENSION_GJS (exten);
  gboolean success = FALSE;
  jsval js_method, js_retval;
  jsval *js_args;
  CachedArg *arg_cache;
  gint i, n_args, nth_out_arg;
  gint n_in_args = 0;
  gint n_out_args = 0;
  gint cached_args = 0;

  /* Fetch the JS method we want to call */
  if (!JS_GetProperty (gexten->js_context, gexten->js_object,
                       method_name, &js_method) ||
      JSVAL_IS_VOID (js_method))
    {
      g_warning ("Method '%s.%s' was not found",
                 g_type_name (exten_type), method_name);
      return FALSE;
    }

  if (JSVAL_IS_NULL (js_method) || !JSVAL_IS_OBJECT (js_method) ||
      !JS_ObjectIsFunction (gexten->js_context, JSVAL_TO_OBJECT (js_method)))
    {
      g_warning ("Method '%s.%s' in not a function",
                 g_type_name (exten_type), method_name);
      return FALSE;
    }

  n_args = g_callable_info_get_n_args (func_info);
  if (n_args < 0)
    {
      g_warn_if_fail (n_args >= 0);
      return FALSE;
    }

  js_args = g_newa (jsval, n_args);
  arg_cache = g_newa (CachedArg, n_args + 1);

  /* Return value is an out arg */
  g_callable_info_load_return_type (func_info, &arg_cache[0].type_info);
  if (g_type_info_get_tag (&arg_cache[0].type_info) != GI_TYPE_TAG_VOID)
    {
      ++n_out_args;
      arg_cache[cached_args++].ptr = &retval->v_pointer;
    }

  /* Handle the arguments */
  for (i = 0; i < n_args; ++i, ++cached_args)
    {
      GIDirection direction;

      g_callable_info_load_arg (func_info, i, &arg_cache[cached_args].arg_info);
      direction = g_arg_info_get_direction (&arg_cache[cached_args].arg_info);
      g_arg_info_load_type (&arg_cache[cached_args].arg_info,
                            &arg_cache[cached_args].type_info);

      if (direction == GI_DIRECTION_IN &&
          !gjs_value_from_g_argument (gexten->js_context, &js_args[n_in_args++],
                                      &arg_cache[cached_args].type_info,
                                      &args[i], TRUE))
        {
          g_warning ("Error failed to convert argument '%s'",
                     g_base_info_get_name (&arg_cache[cached_args].arg_info));
          return FALSE;
        }

      if (direction == GI_DIRECTION_INOUT)
        {
          GIArgument arg;

          peas_gi_pointer_to_argument (&arg_cache[cached_args].type_info,
                                       args[i].v_pointer, &arg);

          if (!gjs_value_from_g_argument (gexten->js_context, &js_args[n_in_args++],
                                          &arg_cache[cached_args].type_info, &arg, TRUE))
            {
              g_warning ("Error failed to convert argument '%s'",
                         g_base_info_get_name (&arg_cache[cached_args].arg_info));
              return FALSE;
            }
        }

      if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
        {
          ++n_out_args;
          arg_cache[cached_args].ptr = args[i].v_pointer;
        }
    }

  success = JS_CallFunctionValue (gexten->js_context, gexten->js_object,
                                  js_method, n_in_args, js_args, &js_retval);

  if (!success)
    {
      if (!gjs_log_exception (gexten->js_context, NULL))
        {
          g_warning ("Error while calling '%s.%s'",
                     g_type_name (exten_type), method_name);
        }

      return FALSE;
    }

  /* First we need to release in argument */
  for (i = 0; i < cached_args; ++i)
    {
      GIDirection direction;

      /* First cached argument may be the return value */
      if (i == 0 && cached_args > n_args)
        continue;

      direction = g_arg_info_get_direction (&arg_cache[i].arg_info);

      if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
        {
          GITransfer transfer;

          transfer = g_arg_info_get_ownership_transfer (&arg_cache[i].arg_info);

          if (!gjs_g_argument_release_in_arg (gexten->js_context, transfer,
                                              &arg_cache[i].type_info,
                                              &args[i]))
            {
              g_warning ("Error failed to release IN argument '%s'",
                         g_base_info_get_name (&arg_cache[i].arg_info));
            }
        }
    }

  /* Check that we have a valid return value */
  if (n_out_args > 1)
    {
      if (!JSVAL_IS_OBJECT (js_retval) ||
          !JS_IsArrayObject (gexten->js_context, JSVAL_TO_OBJECT (js_retval)))
        {
          g_warning ("Error return value is not an array");
          return FALSE;
        }
    }

  /* Set out arguments */
  for (i = 0, nth_out_arg = 0; i < cached_args && success; ++i)
    {
      gboolean is_return_value;

      is_return_value = i == 0 && cached_args > n_args;

      /* Return value does not have a GIArgInfo and is always out */
      if (!is_return_value)
        {
          GIDirection direction;

          direction = g_arg_info_get_direction (&arg_cache[i].arg_info);

          if (direction == GI_DIRECTION_IN)
            continue;
        }

      if (n_out_args == 1)
        {
          success = set_out_arg (gexten->js_context, func_info, is_return_value,
                                 &arg_cache[i].arg_info, &arg_cache[i].type_info,
                                 arg_cache[i].ptr, js_retval);
          break;
        }
      else if (n_out_args > 1)
        {
          jsval js_value;

          if (!JS_GetElement (gexten->js_context, JSVAL_TO_OBJECT (js_retval),
                              nth_out_arg++, &js_value) ||
              js_value == JSVAL_VOID)
            {
              g_warning ("Error failed to get out argument %i", nth_out_arg);
              return FALSE;
            }
          else
            {
              success = set_out_arg (gexten->js_context, func_info,
                                     is_return_value, &arg_cache[i].arg_info,
                                     &arg_cache[i].type_info, arg_cache[i].ptr,
                                     js_value);
            }
        }
    }

  return success;
}
JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsid id, JSBool UNUSED(strict), jsval* vp)
{
	IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
	if (!e)
		return JS_FALSE;

	jsval idval;
	if (!JS_IdToValue(cx, id, &idval))
		return JS_FALSE;

	std::string propName;
	if (!ScriptInterface::FromJSVal(cx, idval, propName))
		return JS_FALSE;

	if (propName == "name")
	{
		std::string value;
		if (!ScriptInterface::FromJSVal(cx, *vp, value))
			return JS_FALSE;
		e->SetName(value);
		return JS_TRUE;
	}

	// Use onWhatever to set event handlers
	if (propName.substr(0, 2) == "on")
	{
		if (!JSVAL_IS_OBJECT(*vp) || !JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(*vp)))
		{
			JS_ReportError(cx, "on- event-handlers must be functions");
			return JS_FALSE;
		}

		CStr eventName (CStr(propName.substr(2)).LowerCase());
		e->SetScriptHandler(eventName, JSVAL_TO_OBJECT(*vp));

		return JS_TRUE;
	}

	// Retrieve the setting's type (and make sure it actually exists)
	EGUISettingType Type;
	if (e->GetSettingType(propName, Type) != PSRETURN_OK)
	{
		JS_ReportError(cx, "Invalid setting '%s'", propName.c_str());
		return JS_TRUE;
	}

	switch (Type)
	{

	case GUIST_CStr:
		{
			std::string value;
			if (!ScriptInterface::FromJSVal(cx, *vp, value))
				return JS_FALSE;

			GUI<CStr>::SetSetting(e, propName, value);
			break;
		}

	case GUIST_CStrW:
		{
			std::wstring value;
			if (!ScriptInterface::FromJSVal(cx, *vp, value))
				return JS_FALSE;

			GUI<CStrW>::SetSetting(e, propName, value);
			break;
		}

	case GUIST_CGUISpriteInstance:
		{
			std::string value;
			if (!ScriptInterface::FromJSVal(cx, *vp, value))
				return JS_FALSE;

			GUI<CGUISpriteInstance>::SetSetting(e, propName, CGUISpriteInstance(value));
			break;
		}

	case GUIST_CGUIString:
		{
			std::wstring value;
			if (!ScriptInterface::FromJSVal(cx, *vp, value))
				return JS_FALSE;

			CGUIString str;
			str.SetValue(value);
			GUI<CGUIString>::SetSetting(e, propName, str);
			break;
		}

	case GUIST_EAlign:
		{
			std::string value;
			if (!ScriptInterface::FromJSVal(cx, *vp, value))
				return JS_FALSE;

			EAlign a;
			if (value == "left") a = EAlign_Left;
			else if (value == "right") a = EAlign_Right;
			else if (value == "center" || value == "centre") a = EAlign_Center;
			else
			{
				JS_ReportError(cx, "Invalid alignment (should be 'left', 'right' or 'center')");
				return JS_FALSE;
			}
			GUI<EAlign>::SetSetting(e, propName, a);
			break;
		}

	case GUIST_EVAlign:
		{
			std::string value;
			if (!ScriptInterface::FromJSVal(cx, *vp, value))
				return JS_FALSE;

			EVAlign a;
			if (value == "top") a = EVAlign_Top;
			else if (value == "bottom") a = EVAlign_Bottom;
			else if (value == "center" || value == "centre") a = EVAlign_Center;
			else
			{
				JS_ReportError(cx, "Invalid alignment (should be 'top', 'bottom' or 'center')");
				return JS_FALSE;
			}
			GUI<EVAlign>::SetSetting(e, propName, a);
			break;
		}

	case GUIST_int:
		{
			int32 value;
			if (JS_ValueToInt32(cx, *vp, &value) == JS_TRUE)
				GUI<int>::SetSetting(e, propName, value);
			else
			{
				JS_ReportError(cx, "Cannot convert value to int");
				return JS_FALSE;
			}
			break;
		}

	case GUIST_float:
		{
			jsdouble value;
			if (JS_ValueToNumber(cx, *vp, &value) == JS_TRUE)
				GUI<float>::SetSetting(e, propName, (float)value);
			else
			{
				JS_ReportError(cx, "Cannot convert value to float");
				return JS_FALSE;
			}
			break;
		}

	case GUIST_bool:
		{
			JSBool value;
			if (JS_ValueToBoolean(cx, *vp, &value) == JS_TRUE)
				GUI<bool>::SetSetting(e, propName, value||0); // ||0 to avoid int-to-bool compiler warnings
			else
			{
				JS_ReportError(cx, "Cannot convert value to bool");
				return JS_FALSE;
			}
			break;
		}

	case GUIST_CClientArea:
		{
			if (JSVAL_IS_STRING(*vp))
			{
				std::wstring value;
				if (!ScriptInterface::FromJSVal(cx, *vp, value))
					return JS_FALSE;

				if (e->SetSetting(propName, value) != PSRETURN_OK)
				{
					JS_ReportError(cx, "Invalid value for setting '%s'", propName.c_str());
					return JS_FALSE;
				}
			}
			else if (JSVAL_IS_OBJECT(*vp) && JS_InstanceOf(cx, JSVAL_TO_OBJECT(*vp), &JSI_GUISize::JSI_class, NULL))
			{
				CClientArea area;
				GUI<CClientArea>::GetSetting(e, propName, area);

				JSObject* obj = JSVAL_TO_OBJECT(*vp);
				#define P(x, y, z) area.x.y = (float)g_ScriptingHost.GetObjectProperty_Double(obj, #z)
					P(pixel,	left,	left);
					P(pixel,	top,	top);
					P(pixel,	right,	right);
					P(pixel,	bottom,	bottom);
					P(percent,	left,	rleft);
					P(percent,	top,	rtop);
					P(percent,	right,	rright);
					P(percent,	bottom,	rbottom);
				#undef P

				GUI<CClientArea>::SetSetting(e, propName, area);
			}
			else
			{
				JS_ReportError(cx, "Size only accepts strings or GUISize objects");
				return JS_FALSE;
			}
			break;
		}

	case GUIST_CColor:
		{
			if (JSVAL_IS_STRING(*vp))
			{
				std::wstring value;
				if (!ScriptInterface::FromJSVal(cx, *vp, value))
					return JS_FALSE;

				if (e->SetSetting(propName, value) != PSRETURN_OK)
				{
					JS_ReportError(cx, "Invalid value for setting '%s'", propName.c_str());
					return JS_FALSE;
				}
			}
			else if (JSVAL_IS_OBJECT(*vp) && JS_InstanceOf(cx, JSVAL_TO_OBJECT(*vp), &JSI_GUIColor::JSI_class, NULL))
			{
				CColor colour;
				JSObject* obj = JSVAL_TO_OBJECT(*vp);
				jsval t; double s;
				#define PROP(x) JS_GetProperty(cx, obj, #x, &t); \
								JS_ValueToNumber(cx, t, &s); \
								colour.x = (float)s
				PROP(r); PROP(g); PROP(b); PROP(a);
				#undef PROP

				GUI<CColor>::SetSetting(e, propName, colour);
			}
			else
			{
				JS_ReportError(cx, "Color only accepts strings or GUIColor objects");
				return JS_FALSE;
			}
			break;
		}

	case GUIST_CGUIList:
		{
			JSObject* obj = JSVAL_TO_OBJECT(*vp);
			jsuint length;
			if (JSVAL_IS_OBJECT(*vp) && JS_GetArrayLength(cx, obj, &length) == JS_TRUE)
			{
				CGUIList list;

				for (int i=0; i<(int)length; ++i)
				{
					jsval element;
					if (! JS_GetElement(cx, obj, i, &element))
					{
						JS_ReportError(cx, "Failed to get list element");
						return JS_FALSE;
					}

					std::wstring value;
					if (!ScriptInterface::FromJSVal(cx, element, value))
						return JS_FALSE;

					CGUIString str;
					str.SetValue(value);
					
					list.m_Items.push_back(str);
				}

				GUI<CGUIList>::SetSetting(e, propName, list);
			}
			else
			{
				JS_ReportError(cx, "List only accepts a GUIList object");
				return JS_FALSE;
			}
			break;
		}

		// TODO Gee: (2004-09-01) EAlign and EVAlign too.

	default:
		JS_ReportError(cx, "Setting '%s' uses an unimplemented type", propName.c_str());
		break;
	}

	return !JS_IsExceptionPending(cx);
}
Exemple #28
0
JSBool
jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
{
    return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
           JS_ObjectIsFunction(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
}
Exemple #29
0
void DBInfo::getProperty(JSContext* cx,
                         JS::HandleObject obj,
                         JS::HandleId id,
                         JS::MutableHandleValue vp) {
    // 2nd look into real values, may be cached collection object
    if (!vp.isUndefined()) {
        auto scope = getScope(cx);
        auto opContext = scope->getOpContext();

        if (opContext && vp.isObject()) {
            ObjectWrapper o(cx, vp);

            if (o.hasOwnField(InternedString::_fullName)) {
                // need to check every time that the collection did not get sharded
                if (haveLocalShardingInfo(opContext, o.getString(InternedString::_fullName)))
                    uasserted(ErrorCodes::BadValue, "can't use sharded collection from db.eval");
            }
        }

        return;
    }

    JS::RootedObject parent(cx);
    if (!JS_GetPrototype(cx, obj, &parent))
        uasserted(ErrorCodes::JSInterpreterFailure, "Couldn't get prototype");

    ObjectWrapper parentWrapper(cx, parent);

    if (parentWrapper.hasOwnField(id)) {
        parentWrapper.getValue(id, vp);
        return;
    }

    IdWrapper idw(cx, id);

    // if starts with '_' we dont return collection, one must use getCollection()
    if (idw.isString()) {
        JSStringWrapper jsstr;
        auto sname = idw.toStringData(&jsstr);
        if (sname.size() == 0 || sname[0] == '_') {
            return;
        }
    }

    // no hit, create new collection
    JS::RootedValue getCollection(cx);
    parentWrapper.getValue(InternedString::getCollection, &getCollection);

    if (!(getCollection.isObject() && JS_ObjectIsFunction(cx, getCollection.toObjectOrNull()))) {
        uasserted(ErrorCodes::BadValue, "getCollection is not a function");
    }

    JS::AutoValueArray<1> args(cx);

    idw.toValue(args[0]);

    JS::RootedValue coll(cx);
    ObjectWrapper(cx, obj).callMethod(getCollection, args, &coll);

    uassert(16861,
            "getCollection returned something other than a collection",
            getScope(cx)->getProto<DBCollectionInfo>().instanceOf(coll));

    // cache collection for reuse, don't enumerate
    ObjectWrapper(cx, obj).defineProperty(id, coll, 0);

    vp.set(coll);
}
void
WrapperPromiseCallback::Call(JSContext* aCx,
                             JS::Handle<JS::Value> aValue)
{
  JSAutoCompartment ac(aCx, mGlobal);
  JS::Rooted<JS::Value> value(aCx, aValue);
  if (!JS_WrapValue(aCx, &value)) {
    NS_WARNING("Failed to wrap value into the right compartment.");
    return;
  }

  ErrorResult rv;

  // If invoking callback threw an exception, run resolver's reject with the
  // thrown exception as argument and the synchronous flag set.
  JS::Rooted<JS::Value> retValue(aCx);
  mCallback->Call(value, &retValue, rv, CallbackObject::eRethrowExceptions);

  rv.WouldReportJSException();

  if (rv.Failed() && rv.IsJSException()) {
    JS::Rooted<JS::Value> value(aCx);
    rv.StealJSException(aCx, &value);

    if (!JS_WrapValue(aCx, &value)) {
      NS_WARNING("Failed to wrap value into the right compartment.");
      return;
    }

    mNextPromise->RejectInternal(aCx, value, Promise::SyncTask);
    return;
  }

  // If the return value is the same as the promise itself, throw TypeError.
  if (retValue.isObject()) {
    JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject());
    Promise* returnedPromise;
    nsresult r = UNWRAP_OBJECT(Promise, valueObj, returnedPromise);

    if (NS_SUCCEEDED(r) && returnedPromise == mNextPromise) {
      const char* fileName = nullptr;
      uint32_t lineNumber = 0;

      // Try to get some information about the callback to report a sane error,
      // but don't try too hard (only deals with scripted functions).
      JS::Rooted<JSObject*> unwrapped(aCx,
        js::CheckedUnwrap(mCallback->Callback()));

      if (unwrapped) {
        JSAutoCompartment ac(aCx, unwrapped);
        if (JS_ObjectIsFunction(aCx, unwrapped)) {
          JS::Rooted<JS::Value> asValue(aCx, JS::ObjectValue(*unwrapped));
          JS::Rooted<JSFunction*> func(aCx, JS_ValueToFunction(aCx, asValue));

          MOZ_ASSERT(func);
          JSScript* script = JS_GetFunctionScript(aCx, func);
          if (script) {
            fileName = JS_GetScriptFilename(script);
            lineNumber = JS_GetScriptBaseLineNumber(aCx, script);
          }
        }
      }

      // We're back in aValue's compartment here.
      JS::Rooted<JSString*> stack(aCx, JS_GetEmptyString(JS_GetRuntime(aCx)));
      JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName));
      if (!fn) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(aCx);
        return;
      }

      JS::Rooted<JSString*> message(aCx,
        JS_NewStringCopyZ(aCx,
          "then() cannot return same Promise that it resolves."));
      if (!message) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(aCx);
        return;
      }

      JS::Rooted<JS::Value> typeError(aCx);
      if (!JS::CreateTypeError(aCx, stack, fn, lineNumber, 0,
                               nullptr, message, &typeError)) {
        // Out of memory. Promise will stay unresolved.
        JS_ClearPendingException(aCx);
        return;
      }

      mNextPromise->RejectInternal(aCx, typeError, Promise::SyncTask);
      return;
    }
  }

  // Otherwise, run resolver's resolve with value and the synchronous flag
  // set.
  if (!JS_WrapValue(aCx, &retValue)) {
    NS_WARNING("Failed to wrap value into the right compartment.");
    return;
  }

  mNextPromise->ResolveInternal(aCx, retValue, Promise::SyncTask);
}