mirror of
https://github.com/ccxvii/mujs.git
synced 2026-09-22 15:13:35 +08:00
Add userdata class.
js_newuserdata(J, tag, ptr) creates a userdata object, wrapping the ptr. It takes the prototype for the new object from the top of the stack, just like js_newcconstructor does. js_touserdata(J, tag, idx) extracts the userdata pointer. Throws a TypeError if the object is not a userdata object with a matching tag. js_isuserdata(J, tag, idx) checks if a value on the stack is a userdata object with a matching tag.
This commit is contained in:
@@ -111,7 +111,8 @@ void js_newnumber(js_State *J, double v);
|
||||
void js_newstring(js_State *J, const char *v);
|
||||
void js_newerror(js_State *J, const char *message);
|
||||
void js_newcfunction(js_State *J, js_CFunction fun, int length);
|
||||
void js_newcconstructor(js_State *J, js_CFunction fun, js_CFunction con);
|
||||
void js_newcconstructor(js_State *J, js_CFunction fun, js_CFunction con, int length);
|
||||
void js_newuserdata(js_State *J, const char *tag, void *data);
|
||||
|
||||
int js_isundefined(js_State *J, int idx);
|
||||
int js_isnull(js_State *J, int idx);
|
||||
@@ -121,10 +122,12 @@ int js_isstring(js_State *J, int idx);
|
||||
int js_isprimitive(js_State *J, int idx);
|
||||
int js_isobject(js_State *J, int idx);
|
||||
int js_iscallable(js_State *J, int idx);
|
||||
int js_isuserdata(js_State *J, const char *tag, int idx);
|
||||
|
||||
int js_toboolean(js_State *J, int idx);
|
||||
double js_tonumber(js_State *J, int idx);
|
||||
const char *js_tostring(js_State *J, int idx);
|
||||
void *js_touserdata(js_State *J, const char *tag, int idx);
|
||||
|
||||
double js_tointeger(js_State *J, int idx);
|
||||
int js_toint32(js_State *J, int idx);
|
||||
|
||||
@@ -19,7 +19,7 @@ static int A_isArray(js_State *J, int argc)
|
||||
void jsB_initarray(js_State *J)
|
||||
{
|
||||
js_pushobject(J, J->Array_prototype);
|
||||
js_newcconstructor(J, jsB_Array, jsB_new_Array);
|
||||
js_newcconstructor(J, jsB_Array, jsB_new_Array, 1);
|
||||
{
|
||||
/* ECMA-262-5 */
|
||||
jsB_propf(J, "isArray", A_isArray, 1);
|
||||
|
||||
+1
-1
@@ -39,6 +39,6 @@ void jsB_initboolean(js_State *J)
|
||||
jsB_propf(J, "toString", Bp_toString, 0);
|
||||
jsB_propf(J, "valueOf", Bp_valueOf, 0);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Boolean, jsB_new_Boolean);
|
||||
js_newcconstructor(J, jsB_Boolean, jsB_new_Boolean, 1);
|
||||
js_defglobal(J, "Boolean", JS_DONTENUM);
|
||||
}
|
||||
|
||||
@@ -711,6 +711,9 @@ void js_dumpvalue(js_State *J, js_Value v)
|
||||
case JS_CSTRING: printf("[String'%s']", v.u.object->u.string); break;
|
||||
case JS_CERROR: printf("[Error %s]", v.u.object->u.string); break;
|
||||
case JS_CITERATOR: printf("[Iterator %p]", v.u.object); break;
|
||||
case JS_CUSERDATA:
|
||||
printf("[Userdata %s %p]", v.u.object->u.user.tag, v.u.object->u.user.data);
|
||||
break;
|
||||
default: printf("[Object %p]", v.u.object); break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -89,13 +89,13 @@ void jsB_initerror(js_State *J)
|
||||
jsB_props(J, "message", "an error has occurred");
|
||||
jsB_propf(J, "toString", Ep_toString, 0);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Error, jsB_Error);
|
||||
js_newcconstructor(J, jsB_Error, jsB_Error, 1);
|
||||
js_defglobal(J, "Error", JS_DONTENUM);
|
||||
|
||||
#define IERROR(NAME) \
|
||||
js_pushobject(J, J->NAME##_prototype); \
|
||||
jsB_props(J, "name", Q(NAME)); \
|
||||
js_newcconstructor(J, jsB_##NAME, jsB_##NAME); \
|
||||
js_newcconstructor(J, jsB_##NAME, jsB_##NAME, 1); \
|
||||
js_defglobal(J, Q(NAME), JS_DONTENUM);
|
||||
|
||||
IERROR(EvalError);
|
||||
|
||||
+1
-1
@@ -98,6 +98,6 @@ void jsB_initfunction(js_State *J)
|
||||
jsB_propf(J, "apply", Fp_apply, 2);
|
||||
jsB_propf(J, "call", Fp_call, 1);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Function, jsB_Function);
|
||||
js_newcconstructor(J, jsB_Function, jsB_Function, 1);
|
||||
js_defglobal(J, "Function", JS_DONTENUM);
|
||||
}
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ void jsB_initnumber(js_State *J)
|
||||
jsB_propf(J, "toExponential", Np_toExponential, 1);
|
||||
jsB_propf(J, "toPrecision", Np_toPrecision, 1);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Number, jsB_new_Number);
|
||||
js_newcconstructor(J, jsB_Number, jsB_new_Number, 1);
|
||||
{
|
||||
jsB_propn(J, "MAX_VALUE", DBL_MAX);
|
||||
jsB_propn(J, "MIN_VALUE", DBL_MIN);
|
||||
|
||||
+9
-2
@@ -37,7 +37,14 @@ static int Op_toString(js_State *J, int argc)
|
||||
case JS_CDATE: js_pushliteral(J, "[object Date]"); break;
|
||||
case JS_CMATH: js_pushliteral(J, "[object Math]"); break;
|
||||
case JS_CITERATOR: js_pushliteral(J, "[Iterator]"); break;
|
||||
default: return 0;
|
||||
case JS_CUSERDATA:
|
||||
js_pushliteral(J, "[object ");
|
||||
js_pushliteral(J, self->u.user.tag);
|
||||
js_concat(J);
|
||||
js_pushliteral(J, "]");
|
||||
js_concat(J);
|
||||
break;
|
||||
default: js_pushliteral(J, "[Object unknown]"); break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -94,6 +101,6 @@ void jsB_initobject(js_State *J)
|
||||
jsB_propf(J, "isPrototypeOf", Op_isPrototypeOf, 1);
|
||||
jsB_propf(J, "propertyIsEnumerable", Op_propertyIsEnumerable, 1);
|
||||
}
|
||||
js_newcconstructor(J, jsB_Object, jsB_new_Object);
|
||||
js_newcconstructor(J, jsB_Object, jsB_new_Object, 1);
|
||||
js_defglobal(J, "Object", JS_DONTENUM);
|
||||
}
|
||||
|
||||
@@ -99,8 +99,14 @@ int js_iscallable(js_State *J, int idx)
|
||||
int js_isiterator(js_State *J, int idx)
|
||||
{
|
||||
const js_Value *v = stackidx(J, idx);
|
||||
if (v->type == JS_TOBJECT)
|
||||
return v->u.object->type == JS_CITERATOR;
|
||||
return v->type == JS_TOBJECT && v->u.object->type == JS_CITERATOR;
|
||||
}
|
||||
|
||||
int js_isuserdata(js_State *J, const char *tag, int idx)
|
||||
{
|
||||
const js_Value *v = stackidx(J, idx);
|
||||
if (v->type == JS_TOBJECT && v->u.object->type == JS_CUSERDATA)
|
||||
return !strcmp(tag, v->u.object->u.user.tag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -162,6 +168,15 @@ js_Value js_toprimitive(js_State *J, int idx, int hint)
|
||||
return jsV_toprimitive(J, stackidx(J, idx), hint);
|
||||
}
|
||||
|
||||
void *js_touserdata(js_State *J, const char *tag, int idx)
|
||||
{
|
||||
const js_Value *v = stackidx(J, idx);
|
||||
if (v->type == JS_TOBJECT && v->u.object->type == JS_CUSERDATA)
|
||||
if (!strcmp(tag, v->u.object->u.user.tag))
|
||||
return v->u.object->u.user.data;
|
||||
js_typeerror(J, "not a %s", tag);
|
||||
}
|
||||
|
||||
/* Stack manipulation */
|
||||
|
||||
void js_pop(js_State *J, int n)
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ void jsB_initstring(js_State *J)
|
||||
//jsB_propf(J, "toLowerCase", Sp_toLowerCase, 0);
|
||||
//jsB_propf(J, "toUpperCase", Sp_toUpperCase, 0);
|
||||
}
|
||||
js_newcconstructor(J, jsB_String, jsB_new_String);
|
||||
js_newcconstructor(J, jsB_String, jsB_new_String, 1);
|
||||
{
|
||||
jsB_propf(J, "fromCharCode", S_fromCharCode, 1);
|
||||
}
|
||||
|
||||
@@ -278,14 +278,14 @@ void js_newcfunction(js_State *J, js_CFunction cfun, int length)
|
||||
}
|
||||
|
||||
/* prototype -- constructor */
|
||||
void js_newcconstructor(js_State *J, js_CFunction cfun, js_CFunction ccon)
|
||||
void js_newcconstructor(js_State *J, js_CFunction cfun, js_CFunction ccon, int length)
|
||||
{
|
||||
js_Object *obj = jsV_newobject(J, JS_CCFUNCTION, J->Function_prototype);
|
||||
obj->u.c.function = cfun;
|
||||
obj->u.c.constructor = ccon;
|
||||
js_pushobject(J, obj); /* proto obj */
|
||||
{
|
||||
js_pushnumber(J, 1);
|
||||
js_pushnumber(J, length);
|
||||
js_defproperty(J, -2, "length", JS_READONLY | JS_DONTENUM | JS_DONTDELETE);
|
||||
js_rot2(J); /* obj proto */
|
||||
js_copy(J, -2); /* obj proto obj */
|
||||
@@ -294,6 +294,21 @@ void js_newcconstructor(js_State *J, js_CFunction cfun, js_CFunction ccon)
|
||||
}
|
||||
}
|
||||
|
||||
void js_newuserdata(js_State *J, const char *tag, void *data)
|
||||
{
|
||||
js_Object *prototype = NULL;
|
||||
js_Object *obj;
|
||||
|
||||
if (js_isobject(J, -1))
|
||||
prototype = js_toobject(J, -1);
|
||||
js_pop(J, 1);
|
||||
|
||||
obj = jsV_newobject(J, JS_CUSERDATA, prototype);
|
||||
obj->u.user.tag = tag;
|
||||
obj->u.user.data = data;
|
||||
js_pushobject(J, obj);
|
||||
}
|
||||
|
||||
/* Non-trivial operations on values. These are implemented using the stack. */
|
||||
|
||||
int js_instanceof(js_State *J)
|
||||
|
||||
Reference in New Issue
Block a user