rm flags in c fn calls
This commit is contained in:
@@ -300,8 +300,6 @@ DEF( set_var_ref1, 1, 1, 1, none_var_ref)
|
|||||||
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
|
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
|
||||||
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
|
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
|
||||||
|
|
||||||
DEF( get_length, 1, 1, 1, none)
|
|
||||||
|
|
||||||
DEF( if_false8, 2, 1, 0, label8)
|
DEF( if_false8, 2, 1, 0, label8)
|
||||||
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
|
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
|
||||||
DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */
|
DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */
|
||||||
|
|||||||
226
source/quickjs.c
226
source/quickjs.c
@@ -994,10 +994,10 @@ static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);
|
|||||||
static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);
|
static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);
|
||||||
static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_obj,
|
JSValueConst this_obj,
|
||||||
int argc, JSValueConst *argv, int flags);
|
int argc, JSValueConst *argv);
|
||||||
static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_obj,
|
JSValueConst this_obj,
|
||||||
int argc, JSValueConst *argv, int flags);
|
int argc, JSValueConst *argv);
|
||||||
static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
|
static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_obj,
|
JSValueConst this_obj,
|
||||||
int argc, JSValue *argv, int flags);
|
int argc, JSValue *argv, int flags);
|
||||||
@@ -1035,7 +1035,7 @@ static void gc_decref_child_dbg(JSRuntime *rt, JSGCObjectHeader *parent,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val);
|
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val);
|
||||||
|
static blob *js_get_blob(JSContext *ctx, JSValueConst val);
|
||||||
static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);
|
static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);
|
||||||
static int JS_ToBoolFree(JSContext *ctx, JSValue val);
|
static int JS_ToBoolFree(JSContext *ctx, JSValue val);
|
||||||
static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);
|
static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);
|
||||||
@@ -1106,7 +1106,7 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
|
|||||||
JSValue **arrpp, uint32_t *countp);
|
JSValue **arrpp, uint32_t *countp);
|
||||||
static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
|
static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_val,
|
JSValueConst this_val,
|
||||||
int argc, JSValueConst *argv, int flags);
|
int argc, JSValueConst *argv);
|
||||||
static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);
|
static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);
|
||||||
static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,
|
static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,
|
||||||
JSGCObjectTypeEnum type);
|
JSGCObjectTypeEnum type);
|
||||||
@@ -4891,13 +4891,6 @@ JSValue JS_NewObject(JSContext *ctx)
|
|||||||
return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT);
|
return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj,
|
|
||||||
JSAtom name, int len)
|
|
||||||
{
|
|
||||||
JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len));
|
|
||||||
JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_name, JS_AtomToString(ctx, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper to check if a value is a bytecode function */
|
/* Helper to check if a value is a bytecode function */
|
||||||
static BOOL js_is_bytecode_function(JSValueConst val)
|
static BOOL js_is_bytecode_function(JSValueConst val)
|
||||||
{
|
{
|
||||||
@@ -5001,15 +4994,13 @@ typedef struct JSCFunctionDataRecord {
|
|||||||
|
|
||||||
static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
|
static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_val,
|
JSValueConst this_val,
|
||||||
int argc, JSValueConst *argv, int flags)
|
int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
JSFunction *f = JS_VALUE_GET_FUNCTION(func_obj);
|
JSFunction *f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||||
JSCFunctionDataRecord *s = f->u.c_function_data_record;
|
JSCFunctionDataRecord *s = f->u.c_function_data_record;
|
||||||
JSValueConst *arg_buf;
|
JSValueConst *arg_buf;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
(void)flags; /* unused */
|
|
||||||
|
|
||||||
/* XXX: could add the function on the stack for debug */
|
/* XXX: could add the function on the stack for debug */
|
||||||
if (unlikely(argc < s->length)) {
|
if (unlikely(argc < s->length)) {
|
||||||
arg_buf = alloca(sizeof(arg_buf[0]) * s->length);
|
arg_buf = alloca(sizeof(arg_buf[0]) * s->length);
|
||||||
@@ -9095,29 +9086,6 @@ static void js_print_atom(JSPrintValueState *s, JSAtom atom)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return 0 if invalid length */
|
|
||||||
static uint32_t js_print_array_get_length(JSObject *p)
|
|
||||||
{
|
|
||||||
JSProperty *pr;
|
|
||||||
JSShapeProperty *prs;
|
|
||||||
JSValueConst val;
|
|
||||||
|
|
||||||
prs = find_own_property(&pr, p, JS_ATOM_length);
|
|
||||||
if (!prs)
|
|
||||||
return 0;
|
|
||||||
if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)
|
|
||||||
return 0;
|
|
||||||
val = pr->u.value;
|
|
||||||
switch(JS_VALUE_GET_NORM_TAG(val)) {
|
|
||||||
case JS_TAG_INT:
|
|
||||||
return JS_VALUE_GET_INT(val);
|
|
||||||
case JS_TAG_FLOAT64:
|
|
||||||
return (uint32_t)JS_VALUE_GET_FLOAT64(val);
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void js_print_comma(JSPrintValueState *s, int *pcomma_state)
|
static void js_print_comma(JSPrintValueState *s, int *pcomma_state)
|
||||||
{
|
{
|
||||||
switch(*pcomma_state) {
|
switch(*pcomma_state) {
|
||||||
@@ -10213,7 +10181,7 @@ static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int var_idx)
|
|||||||
|
|
||||||
static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_obj,
|
JSValueConst this_obj,
|
||||||
int argc, JSValueConst *argv, int flags)
|
int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
JSRuntime *rt = ctx->rt;
|
JSRuntime *rt = ctx->rt;
|
||||||
JSCFunctionType func;
|
JSCFunctionType func;
|
||||||
@@ -10224,7 +10192,6 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
|||||||
int arg_count, i;
|
int arg_count, i;
|
||||||
JSCFunctionEnum cproto;
|
JSCFunctionEnum cproto;
|
||||||
|
|
||||||
(void)flags; /* unused */
|
|
||||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||||
cproto = f->u.cfunc.cproto;
|
cproto = f->u.cfunc.cproto;
|
||||||
arg_count = f->length;
|
arg_count = f->length;
|
||||||
@@ -10314,7 +10281,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
|||||||
|
|
||||||
static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_obj,
|
JSValueConst this_obj,
|
||||||
int argc, JSValueConst *argv, int flags)
|
int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
JSFunction *f;
|
JSFunction *f;
|
||||||
JSBoundFunction *bf;
|
JSBoundFunction *bf;
|
||||||
@@ -10322,7 +10289,6 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
|||||||
int arg_count, i;
|
int arg_count, i;
|
||||||
|
|
||||||
(void)this_obj; /* unused - bound function uses bf->this_val */
|
(void)this_obj; /* unused - bound function uses bf->this_val */
|
||||||
(void)flags; /* unused */
|
|
||||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||||
bf = f->u.bound_function;
|
bf = f->u.bound_function;
|
||||||
arg_count = bf->argc + argc;
|
arg_count = bf->argc + argc;
|
||||||
@@ -10473,13 +10439,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
switch (f->kind) {
|
switch (f->kind) {
|
||||||
case JS_FUNC_KIND_C:
|
case JS_FUNC_KIND_C:
|
||||||
return js_call_c_function(caller_ctx, func_obj, this_obj, argc,
|
return js_call_c_function(caller_ctx, func_obj, this_obj, argc,
|
||||||
(JSValueConst *)argv, flags);
|
(JSValueConst *)argv);
|
||||||
case JS_FUNC_KIND_BOUND:
|
case JS_FUNC_KIND_BOUND:
|
||||||
return js_call_bound_function(caller_ctx, func_obj, this_obj, argc,
|
return js_call_bound_function(caller_ctx, func_obj, this_obj, argc,
|
||||||
(JSValueConst *)argv, flags);
|
(JSValueConst *)argv);
|
||||||
case JS_FUNC_KIND_C_DATA:
|
case JS_FUNC_KIND_C_DATA:
|
||||||
return js_c_function_data_call(caller_ctx, func_obj, this_obj, argc,
|
return js_c_function_data_call(caller_ctx, func_obj, this_obj, argc,
|
||||||
(JSValueConst *)argv, flags);
|
(JSValueConst *)argv);
|
||||||
case JS_FUNC_KIND_BYTECODE:
|
case JS_FUNC_KIND_BYTECODE:
|
||||||
break; /* continue to bytecode execution below */
|
break; /* continue to bytecode execution below */
|
||||||
default:
|
default:
|
||||||
@@ -10594,24 +10560,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
CASE(OP_push_empty_string):
|
CASE(OP_push_empty_string):
|
||||||
*sp++ = JS_AtomToString(ctx, JS_ATOM_empty_string);
|
*sp++ = JS_AtomToString(ctx, JS_ATOM_empty_string);
|
||||||
BREAK;
|
BREAK;
|
||||||
CASE(OP_get_length):
|
|
||||||
{
|
|
||||||
JSValue val;
|
|
||||||
|
|
||||||
/* Functions don't support property access in cell script */
|
|
||||||
if (js_is_proxy_callable(sp[-1])) {
|
|
||||||
JS_ThrowTypeError(ctx, "cannot get property of function");
|
|
||||||
goto exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf->cur_pc = pc;
|
|
||||||
val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length);
|
|
||||||
if (unlikely(JS_IsException(val)))
|
|
||||||
goto exception;
|
|
||||||
JS_FreeValue(ctx, sp[-1]);
|
|
||||||
sp[-1] = val;
|
|
||||||
}
|
|
||||||
BREAK;
|
|
||||||
#endif
|
#endif
|
||||||
CASE(OP_push_atom_value):
|
CASE(OP_push_atom_value):
|
||||||
*sp++ = JS_AtomToValue(ctx, get_u32(pc));
|
*sp++ = JS_AtomToValue(ctx, get_u32(pc));
|
||||||
@@ -15844,64 +15792,34 @@ static __exception int js_parse_left_hand_side_expr(JSParseState *s)
|
|||||||
return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
|
return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ARRAY_LITERAL_MAX 1024
|
||||||
|
|
||||||
static __exception int js_parse_array_literal(JSParseState *s)
|
static __exception int js_parse_array_literal(JSParseState *s)
|
||||||
{
|
{
|
||||||
uint32_t idx;
|
uint32_t idx = 0;
|
||||||
BOOL need_length;
|
|
||||||
|
|
||||||
if (next_token(s))
|
if (next_token(s)) return -1;
|
||||||
return -1;
|
|
||||||
/* small regular arrays are created on the stack */
|
|
||||||
idx = 0;
|
|
||||||
while (s->token.val != ']' && idx < 32) {
|
|
||||||
if (s->token.val == ',')
|
|
||||||
break;
|
|
||||||
if (js_parse_assign_expr(s))
|
|
||||||
return -1;
|
|
||||||
idx++;
|
|
||||||
/* accept trailing comma */
|
|
||||||
if (s->token.val == ',') {
|
|
||||||
if (next_token(s))
|
|
||||||
return -1;
|
|
||||||
} else
|
|
||||||
if (s->token.val != ']')
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
emit_op(s, OP_array_from);
|
|
||||||
emit_u16(s, idx);
|
|
||||||
|
|
||||||
/* larger arrays and holes are handled with explicit indices */
|
while (s->token.val != ']' && idx < ARRAY_LITERAL_MAX) {
|
||||||
need_length = FALSE;
|
if (s->token.val == ',')
|
||||||
while (s->token.val != ']' && idx < 0x7fffffff) {
|
return js_parse_error(s, "array holes not allowed");
|
||||||
need_length = TRUE;
|
|
||||||
if (s->token.val != ',') {
|
if (js_parse_assign_expr(s)) return -1;
|
||||||
JSAtom atom;
|
idx++;
|
||||||
if (js_parse_assign_expr(s))
|
|
||||||
return -1;
|
if (s->token.val == ',') {
|
||||||
atom = JS_NewAtomUInt32(s->ctx, idx);
|
if (next_token(s)) return -1;
|
||||||
emit_op(s, OP_define_field);
|
} else if (s->token.val != ']') {
|
||||||
emit_atom(s, atom);
|
return js_parse_error(s, "expected ',' or ']'");
|
||||||
JS_FreeAtom(s->ctx, atom);
|
|
||||||
need_length = FALSE;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
/* accept trailing comma */
|
|
||||||
if (s->token.val == ',') {
|
|
||||||
if (next_token(s))
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (need_length) {
|
}
|
||||||
/* Set the length: Cannot use OP_define_field because
|
|
||||||
length is not configurable */
|
if (s->token.val != ']')
|
||||||
emit_op(s, OP_dup);
|
return js_parse_error(s, "array literal too long");
|
||||||
emit_op(s, OP_push_i32);
|
|
||||||
emit_u32(s, idx);
|
emit_op(s, OP_array_from);
|
||||||
emit_op(s, OP_put_field);
|
emit_u16(s, idx);
|
||||||
emit_atom(s, JS_ATOM_length);
|
return js_parse_expect(s, ']');
|
||||||
}
|
|
||||||
done:
|
|
||||||
return js_parse_expect(s, ']');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: remove */
|
/* XXX: remove */
|
||||||
@@ -21167,18 +21085,6 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto no_change;
|
goto no_change;
|
||||||
|
|
||||||
case OP_get_field:
|
|
||||||
if (OPTIMIZE) {
|
|
||||||
JSAtom atom = get_u32(bc_buf + pos + 1);
|
|
||||||
if (atom == JS_ATOM_length) {
|
|
||||||
JS_FreeAtom(ctx, atom);
|
|
||||||
add_pc2line_info(s, bc_out.size, line_num);
|
|
||||||
dbuf_putc(&bc_out, OP_get_length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto no_change;
|
|
||||||
#endif
|
#endif
|
||||||
case OP_push_atom_value:
|
case OP_push_atom_value:
|
||||||
if (OPTIMIZE) {
|
if (OPTIMIZE) {
|
||||||
@@ -23262,49 +23168,6 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int JS_WriteArray(BCWriterState *s, JSValueConst obj)
|
|
||||||
{
|
|
||||||
JSObject *p = JS_VALUE_GET_OBJ(obj);
|
|
||||||
uint32_t i, len;
|
|
||||||
JSValue val;
|
|
||||||
int ret;
|
|
||||||
BOOL is_template;
|
|
||||||
|
|
||||||
if (s->allow_bytecode && p->stone) {
|
|
||||||
/* not extensible array: we consider it is a
|
|
||||||
template when we are saving bytecode */
|
|
||||||
bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT);
|
|
||||||
is_template = TRUE;
|
|
||||||
} else {
|
|
||||||
bc_put_u8(s, BC_TAG_ARRAY);
|
|
||||||
is_template = FALSE;
|
|
||||||
}
|
|
||||||
if (js_get_length32(s->ctx, &len, obj))
|
|
||||||
goto fail1;
|
|
||||||
bc_put_leb128(s, len);
|
|
||||||
for(i = 0; i < len; i++) {
|
|
||||||
val = JS_GetPropertyUint32(s->ctx, obj, i);
|
|
||||||
if (JS_IsException(val))
|
|
||||||
goto fail1;
|
|
||||||
ret = JS_WriteObjectRec(s, val);
|
|
||||||
JS_FreeValue(s->ctx, val);
|
|
||||||
if (ret)
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
if (is_template) {
|
|
||||||
val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw);
|
|
||||||
if (JS_IsException(val))
|
|
||||||
goto fail1;
|
|
||||||
ret = JS_WriteObjectRec(s, val);
|
|
||||||
JS_FreeValue(s->ctx, val);
|
|
||||||
if (ret)
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
fail1:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)
|
static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)
|
||||||
{
|
{
|
||||||
JSObject *p = JS_VALUE_GET_OBJ(obj);
|
JSObject *p = JS_VALUE_GET_OBJ(obj);
|
||||||
@@ -24549,12 +24412,33 @@ static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val,
|
|||||||
static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
|
static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
|
||||||
JSValueConst obj)
|
JSValueConst obj)
|
||||||
{
|
{
|
||||||
|
int tag = JS_VALUE_GET_TAG(obj);
|
||||||
|
|
||||||
/* Fast path for intrinsic arrays */
|
/* Fast path for intrinsic arrays */
|
||||||
if (JS_VALUE_GET_TAG(obj) == JS_TAG_ARRAY) {
|
if (tag == JS_TAG_ARRAY) {
|
||||||
JSArray *arr = JS_VALUE_GET_ARRAY(obj);
|
JSArray *arr = JS_VALUE_GET_ARRAY(obj);
|
||||||
*pres = arr->len;
|
*pres = arr->len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tag == JS_TAG_FUNCTION) {
|
||||||
|
JSFunction *fn = JS_VALUE_GET_FUNCTION(obj);
|
||||||
|
*pres = fn->length;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blob *b = js_get_blob(ctx, obj);
|
||||||
|
if (b) {
|
||||||
|
*pres = b->length;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag == JS_TAG_STRING || tag == JS_TAG_STRING_ROPE) {
|
||||||
|
JSString *p = JS_VALUE_GET_STRING(obj);
|
||||||
|
*pres = p->len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
JSValue len_val;
|
JSValue len_val;
|
||||||
len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);
|
len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);
|
||||||
if (JS_IsException(len_val)) {
|
if (JS_IsException(len_val)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user