ref: 1a7d3ea1e615b6d49f2906c1af24b94b319c8476
parent: 90b54a9eecd56972de90ed69e377b9469b0274de
author: Tor Andersson <[email protected]>
date: Fri Jan 24 14:04:04 EST 2014
Refactor property get/set internals.
--- a/js.h
+++ b/js.h
@@ -90,7 +90,6 @@
void js_setglobal(js_State *J, const char *name);
void js_defglobal(js_State *J, const char *name, int atts);
-void js_getownproperty(js_State *J, int idx, const char *name);
void js_getproperty(js_State *J, int idx, const char *name);
void js_setproperty(js_State *J, int idx, const char *name);
void js_defproperty(js_State *J, int idx, const char *name, int atts);
--- a/jsrun.c
+++ b/jsrun.c
@@ -266,11 +266,11 @@
STACK[TOP-i] = tmp;
}
-/* Registry, global and object property accessors */
+/* Property access that takes care of attributes and getters/setters */
-void js_getregistry(js_State *J, const char *name)
+static void jsR_getproperty(js_State *J, js_Object *obj, const char *name)
{
- js_Property *ref = jsV_getproperty(J, J->R, name);
+ js_Property *ref = jsV_getproperty(J, obj, name);
if (ref)
js_pushvalue(J, ref->value);
else
@@ -277,19 +277,29 @@
js_pushundefined(J);
}
-void js_setregistry(js_State *J, const char *name)
+static void jsR_setproperty(js_State *J, js_Object *obj, const char *name, js_Value v)
{
- js_Property *ref = jsV_setproperty(J, J->R, name);
- if (ref)
- ref->value = js_tovalue(J, -1);
- js_pop(J, 1);
+ js_Property *ref = jsV_setproperty(J, obj, name);
+ if (ref && !(ref->atts & JS_READONLY))
+ ref->value = v;
}
-void js_delregistry(js_State *J, const char *name)
+static void jsR_defproperty(js_State *J, js_Object *obj, const char *name, js_Value v, int atts)
{
+ js_Property *ref = jsV_setproperty(J, obj, name);
+ if (ref) {
+ ref->value = v;
+ ref->atts = atts;
+ }
+}
+
+static void jsR_delproperty(js_State *J, js_Object *obj, const char *name)
+{
// TODO
}
+/* Registry, global and object property accessors */
+
const char *js_ref(js_State *J)
{
const js_Value *v = stackidx(J, -1);
@@ -319,73 +329,61 @@
js_delregistry(J, ref);
}
+void js_getregistry(js_State *J, const char *name)
+{
+ jsR_getproperty(J, J->R, name);
+}
+
+void js_setregistry(js_State *J, const char *name)
+{
+ jsR_setproperty(J, J->R, name, js_tovalue(J, -1));
+ js_pop(J, 1);
+}
+
+void js_delregistry(js_State *J, const char *name)
+{
+ jsR_delproperty(J, J->R, name);
+}
+
void js_getglobal(js_State *J, const char *name)
{
- js_Property *ref = jsV_getproperty(J, J->G, name);
- if (ref)
- js_pushvalue(J, ref->value);
- else
- js_pushundefined(J);
+ jsR_getproperty(J, J->G, name);
}
void js_setglobal(js_State *J, const char *name)
{
- js_Property *ref = jsV_setproperty(J, J->G, name);
- if (ref)
- ref->value = js_tovalue(J, -1);
+ jsR_setproperty(J, J->G, name, js_tovalue(J, -1));
js_pop(J, 1);
}
void js_defglobal(js_State *J, const char *name, int atts)
{
- js_Property *ref = jsV_setproperty(J, J->G, name);
- if (ref) {
- ref->value = js_tovalue(J, -1);
- ref->atts = atts;
- }
+ jsR_defproperty(J, J->G, name, js_tovalue(J, -1), atts);
js_pop(J, 1);
}
-void js_getownproperty(js_State *J, int idx, const char *name)
-{
- js_Object *obj = js_toobject(J, idx);
- js_Property *ref = jsV_getownproperty(J, obj, name);
- if (ref)
- js_pushvalue(J, ref->value);
- else
- js_pushundefined(J);
-}
-
void js_getproperty(js_State *J, int idx, const char *name)
{
- js_Object *obj = js_toobject(J, idx);
- js_Property *ref = jsV_getproperty(J, obj, name);
- if (ref)
- js_pushvalue(J, ref->value);
- else
- js_pushundefined(J);
+ jsR_getproperty(J, js_toobject(J, idx), name);
}
void js_setproperty(js_State *J, int idx, const char *name)
{
- js_Object *obj = js_toobject(J, idx);
- js_Property *ref = jsV_setproperty(J, obj, name);
- if (ref)
- ref->value = js_tovalue(J, -1);
+ jsR_setproperty(J, js_toobject(J, idx), name, js_tovalue(J, -1));
js_pop(J, 1);
}
void js_defproperty(js_State *J, int idx, const char *name, int atts)
{
- js_Object *obj = js_toobject(J, idx);
- js_Property *ref = jsV_setproperty(J, obj, name);
- if (ref) {
- ref->value = js_tovalue(J, -1);
- ref->atts = atts;
- }
+ jsR_defproperty(J, js_toobject(J, idx), name, js_tovalue(J, -1), atts);
js_pop(J, 1);
}
+void js_delproperty(js_State *J, int idx, const char *name)
+{
+ jsR_delproperty(J, js_toobject(J, idx), name);
+}
+
/* Environment records */
js_Environment *jsR_newenvironment(js_State *J, js_Object *vars, js_Environment *outer)
@@ -401,33 +399,40 @@
return E;
}
-static js_Property *js_decvar(js_State *J, const char *name)
+static void js_decvar(js_State *J, const char *name, js_Value v)
{
- return jsV_setproperty(J, J->E->variables, name);
+ jsR_setproperty(J, J->E->variables, name, v);
}
-static js_Property *js_getvar(js_State *J, const char *name)
+static void js_getvar(js_State *J, const char *name)
{
js_Environment *E = J->E;
do {
js_Property *ref = jsV_getproperty(J, E->variables, name);
- if (ref)
- return ref;
+ if (ref) {
+ // TODO: use getter
+ js_pushvalue(J, ref->value);
+ return;
+ }
E = E->outer;
} while (E);
- return NULL;
+ js_referenceerror(J, "%s is not defined", name);
}
-static js_Property *js_setvar(js_State *J, const char *name)
+static void js_setvar(js_State *J, const char *name)
{
js_Environment *E = J->E;
do {
js_Property *ref = jsV_getproperty(J, E->variables, name);
- if (ref)
- return ref;
+ if (ref) {
+ // TODO: use setter
+ if (!(ref->atts & JS_READONLY))
+ ref->value = js_tovalue(J, -1);
+ return;
+ }
E = E->outer;
} while (E);
- return jsV_setproperty(J, J->G, name);
+ jsR_setproperty(J, J->G, name, js_tovalue(J, -1));
}
/* Function calls */
@@ -442,9 +447,13 @@
J->E = jsR_newenvironment(J, jsV_newobject(J, JS_COBJECT, NULL), scope);
for (i = 0; i < F->numparams; ++i) {
- js_Property *ref = js_decvar(J, F->params[i]);
if (i < n)
- ref->value = js_tovalue(J, i + 1);
+ js_decvar(J, F->params[i], js_tovalue(J, i + 1));
+ else {
+ js_pushundefined(J);
+ js_decvar(J, F->params[i], js_tovalue(J, -1));
+ js_pop(J, 1);
+ }
}
js_pop(J, n);
@@ -608,7 +617,6 @@
const char *str;
js_Object *obj;
- js_Property *ref;
double x, y;
unsigned int ux, uy;
int ix, iy;
@@ -652,29 +660,22 @@
case OP_GLOBAL: js_pushobject(J, J->G); break;
case OP_FUNDEC:
- ref = js_decvar(J, ST[*pc++]);
- if (ref)
- ref->value = js_tovalue(J, -1);
+ js_decvar(J, ST[*pc++], js_tovalue(J, -1));
js_pop(J, 1);
break;
case OP_VARDEC:
- ref = js_decvar(J, ST[*pc++]);
+ js_pushundefined(J);
+ js_decvar(J, ST[*pc++], js_tovalue(J, -1));
+ js_pop(J, 1);
break;
case OP_GETVAR:
- str = ST[*pc++];
- ref = js_getvar(J, str);
- if (ref)
- js_pushvalue(J, ref->value);
- else
- js_referenceerror(J, "%s is not defined", str);
+ js_getvar(J, ST[*pc++]);
break;
case OP_SETVAR:
- ref = js_setvar(J, ST[*pc++]);
- if (ref)
- ref->value = js_tovalue(J, -1);
+ js_setvar(J, ST[*pc++]);
break;
// OP_DELVAR
@@ -682,44 +683,29 @@
case OP_IN:
str = js_tostring(J, -2);
obj = js_toobject(J, -1);
- ref = jsV_getproperty(J, obj, str);
+ b = jsV_getproperty(J, obj, str) != NULL;
js_pop(J, 2);
- js_pushboolean(J, ref != NULL);
+ js_pushboolean(J, b);
break;
case OP_GETPROP:
str = js_tostring(J, -1);
- js_pop(J, 1);
- js_getproperty(J, -1, str);
-
obj = js_toobject(J, -2);
- ref = jsV_getproperty(J, obj, str);
- js_pop(J, 2);
- if (ref)
- js_pushvalue(J, ref->value);
- else
- js_pushundefined(J);
+ jsR_getproperty(J, obj, str);
+ js_rot3pop2(J);
break;
case OP_GETPROPS:
str = ST[*pc++];
- js_getproperty(J, -1, str);
-
- obj = js_toobject(J, -2);
- ref = jsV_getproperty(J, obj, str);
- js_pop(J, 2);
- if (ref)
- js_pushvalue(J, ref->value);
- else
- js_pushundefined(J);
+ obj = js_toobject(J, -1);
+ jsR_getproperty(J, obj, str);
+ js_rot2pop1(J);
break;
case OP_SETPROP:
obj = js_toobject(J, -3);
str = js_tostring(J, -2);
- ref = jsV_setproperty(J, obj, str);
- if (ref)
- ref->value = js_tovalue(J, -1);
+ jsR_setproperty(J, obj, str, js_tovalue(J, -1));
js_rot3pop2(J);
break;
@@ -726,14 +712,23 @@
case OP_SETPROPS:
str = ST[*pc++];
obj = js_toobject(J, -2);
- ref = jsV_setproperty(J, obj, str);
- if (ref)
- ref->value = js_tovalue(J, -1);
+ jsR_setproperty(J, obj, str, js_tovalue(J, -1));
js_rot2pop1(J);
break;
- // OP_DELPROP
- // OP_DELPROPS
+ case OP_DELPROP:
+ obj = js_toobject(J, -3);
+ str = js_tostring(J, -2);
+ jsR_delproperty(J, obj, str);
+ js_pop(J, 2);
+ break;
+
+ case OP_DELPROPS:
+ str = ST[*pc++];
+ obj = js_toobject(J, -2);
+ jsR_delproperty(J, obj, str);
+ js_pop(J, 1);
+ break;
case OP_ITERATOR:
if (!js_isundefined(J, -1) && !js_isnull(J, -1)) {