ref: 3cef8607dca6efac918085f0a1d9aebbbc7da2a8
parent: b22dc395c99510adc9e7f15906accd8897be289c
author: Tor Andersson <tor@ccxvii.net>
date: Fri Jan 24 11:17:43 EST 2014
Add a registry for stashing hidden javascript objects from C code.
--- a/js.h
+++ b/js.h
@@ -79,6 +79,13 @@
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);
--- a/jsgc.c
+++ b/jsgc.c
@@ -124,6 +124,7 @@
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);
--- a/jsi.h
+++ b/jsi.h
@@ -106,8 +106,10 @@
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;
--- a/jsrun.c
+++ b/jsrun.c
@@ -251,7 +251,58 @@
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)
{
--- a/jsstate.c
+++ b/jsstate.c
@@ -107,7 +107,9 @@
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);