diff --git a/js.h b/js.h index e0f9ae5..bb8466d 100644 --- a/js.h +++ b/js.h @@ -79,6 +79,13 @@ void js_loadfile(js_State *J, const char *filename); void js_call(js_State *J, int n); void js_construct(js_State *J, int n); +const char *js_ref(js_State *J); +void js_unref(js_State *J, const char *ref); + +void js_getregistry(js_State *J, const char *name); +void js_setregistry(js_State *J, const char *name); +void js_delregistry(js_State *J, const char *name); + void js_getglobal(js_State *J, const char *name); void js_setglobal(js_State *J, const char *name); void js_defglobal(js_State *J, const char *name, int atts); diff --git a/jsgc.c b/jsgc.c index 592496f..679ed58 100644 --- a/jsgc.c +++ b/jsgc.c @@ -124,6 +124,7 @@ void js_gc(js_State *J, int report) jsG_markobject(J, mark, J->TypeError_prototype); jsG_markobject(J, mark, J->URIError_prototype); + jsG_markobject(J, mark, J->R); jsG_markobject(J, mark, J->G); jsG_markstack(J, mark); diff --git a/jsi.h b/jsi.h index 19a5052..754ec28 100644 --- a/jsi.h +++ b/jsi.h @@ -106,8 +106,10 @@ struct js_State js_Object *TypeError_prototype; js_Object *URIError_prototype; - js_Object *G; - js_Environment *E; + int nextref; /* for js_ref use */ + js_Object *R; /* registry of hidden values */ + js_Object *G; /* the global object */ + js_Environment *E; /* current environment scope */ /* execution stack */ int top, bot; diff --git a/jsrun.c b/jsrun.c index 71ee13f..1f96a73 100644 --- a/jsrun.c +++ b/jsrun.c @@ -251,7 +251,58 @@ void js_rot(js_State *J, int n) STACK[TOP-i] = tmp; } -/* Global and object property accessors */ +/* Registry, global and object property accessors */ + +void js_getregistry(js_State *J, const char *name) +{ + js_Property *ref = jsV_getproperty(J, J->R, name); + if (ref) + js_pushvalue(J, ref->value); + else + js_pushundefined(J); +} + +void js_setregistry(js_State *J, const char *name) +{ + js_Property *ref = jsV_setproperty(J, J->R, name); + if (ref) + ref->value = js_tovalue(J, -1); + js_pop(J, 1); +} + +void js_delregistry(js_State *J, const char *name) +{ + // TODO +} + +const char *js_ref(js_State *J) +{ + const js_Value *v = stackidx(J, -1); + const char *s; + char buf[32]; + switch (v->type) { + case JS_TUNDEFINED: s = "_Undefined"; break; + case JS_TNULL: s = "_Null"; break; + case JS_TBOOLEAN: + s = v->u.boolean ? "_True" : "_False"; + break; + case JS_TOBJECT: + sprintf(buf, "%p", v->u.object); + s = js_intern(J, buf); + break; + default: + sprintf(buf, "%d", J->nextref++); + s = js_intern(J, buf); + break; + } + js_setregistry(J, s); + return s; +} + +void js_unref(js_State *J, const char *ref) +{ + js_delregistry(J, ref); +} void js_getglobal(js_State *J, const char *name) { diff --git a/jsstate.c b/jsstate.c index 17fb19f..b90a092 100644 --- a/jsstate.c +++ b/jsstate.c @@ -107,7 +107,9 @@ js_State *js_newstate(void) J->stack = malloc(JS_STACKSIZE * sizeof *J->stack); J->gcmark = 1; + J->nextref = 0; + J->R = jsV_newobject(J, JS_COBJECT, NULL); J->G = jsV_newobject(J, JS_COBJECT, NULL); J->E = jsR_newenvironment(J, J->G, NULL);