Set prototype internal property when creating objects.

This commit is contained in:
Tor Andersson
2014-01-17 19:41:41 +01:00
parent 5ce44f9d4a
commit f487a7db10
8 changed files with 150 additions and 54 deletions

114
jsbuiltin.c Normal file
View File

@@ -0,0 +1,114 @@
#include "js.h"
#include "jsobject.h"
#include "jsrun.h"
#include "jsstate.h"
static int jsB_print(js_State *J, int argc)
{
int i;
for (i = 1; i < argc; ++i) {
const char *s = js_tostring(J, i);
if (i > 1) putchar(' ');
fputs(s, stdout);
}
putchar('\n');
return 0;
}
static int jsB_eval(js_State *J, int argc)
{
const char *s;
if (!js_isstring(J, -1))
return 1;
// FIXME: return value if eval string is an expression
s = js_tostring(J, -1);
if (jsR_loadscript(J, "(eval)", s))
jsR_error(J, "SyntaxError (eval)");
js_dup(J, 0); /* copy this */
js_call(J, 0);
return 1;
}
static int jsB_Object(js_State *J, int n) { return 0; }
static int jsB_Array(js_State *J, int n) { return 0; }
static int jsB_Function(js_State *J, int n) { return 0; }
static int jsB_Boolean(js_State *J, int n) { return 0; }
static int jsB_Number(js_State *J, int n) { return 0; }
static int jsB_String(js_State *J, int n) { return 0; }
static void jsB_initobject(js_State *J)
{
J->Object_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_pushcfunction(J, jsB_Object);
js_pushobject(J, J->Object_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Object");
}
static void jsB_initarray(js_State *J)
{
J->Array_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_pushcfunction(J, jsB_Array);
js_pushobject(J, J->Array_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Array");
}
static void jsB_initfunction(js_State *J)
{
J->Function_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_pushcfunction(J, jsB_Function);
js_pushobject(J, J->Function_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Function");
}
static void jsB_initboolean(js_State *J)
{
J->Boolean_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_pushcfunction(J, jsB_Boolean);
js_pushobject(J, J->Boolean_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Boolean");
}
static void jsB_initnumber(js_State *J)
{
J->Number_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_pushcfunction(J, jsB_Number);
js_pushobject(J, J->Number_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "Number");
}
static void jsB_initstring(js_State *J)
{
J->String_prototype = jsR_newobject(J, JS_COBJECT, NULL);
js_pushcfunction(J, jsB_String);
js_pushobject(J, J->String_prototype);
js_setproperty(J, -2, "prototype");
js_setglobal(J, "String");
}
static void jsB_register(js_State *J, const char *name, js_CFunction cfun)
{
js_pushcfunction(J, cfun);
js_setglobal(J, name);
}
void jsB_init(js_State *J)
{
jsB_initobject(J);
jsB_initarray(J);
jsB_initfunction(J);
jsB_initboolean(J);
jsB_initnumber(J);
jsB_initstring(J);
jsB_register(J, "eval", jsB_eval);
jsB_register(J, "print", jsB_print);
}

View File

@@ -1,9 +1,10 @@
#include "js.h"
#include "jsobject.h"
#include "jsstate.h"
js_Object *jsR_newfunction(js_State *J, js_Function *function, js_Environment *scope)
{
js_Object *obj = jsR_newobject(J, JS_CFUNCTION);
js_Object *obj = jsR_newobject(J, JS_CFUNCTION, J->Function_prototype);
obj->function = function;
obj->scope = scope;
return obj;
@@ -11,35 +12,35 @@ js_Object *jsR_newfunction(js_State *J, js_Function *function, js_Environment *s
js_Object *jsR_newscript(js_State *J, js_Function *function)
{
js_Object *obj = jsR_newobject(J, JS_CSCRIPT);
js_Object *obj = jsR_newobject(J, JS_CSCRIPT, NULL);
obj->function = function;
return obj;
}
js_Object *jsR_newcfunction(js_State *J, js_CFunction cfunction)
{
js_Object *obj = jsR_newobject(J, JS_CCFUNCTION);
js_Object *obj = jsR_newobject(J, JS_CCFUNCTION, NULL);
obj->cfunction = cfunction;
return obj;
}
js_Object *jsR_newboolean(js_State *J, int v)
{
js_Object *obj = jsR_newobject(J, JS_CBOOLEAN);
js_Object *obj = jsR_newobject(J, JS_CBOOLEAN, J->Boolean_prototype);
obj->primitive.boolean = v;
return obj;
}
js_Object *jsR_newnumber(js_State *J, double v)
{
js_Object *obj = jsR_newobject(J, JS_CNUMBER);
js_Object *obj = jsR_newobject(J, JS_CNUMBER, J->Number_prototype);
obj->primitive.number = v;
return obj;
}
js_Object *jsR_newstring(js_State *J, const char *v)
{
js_Object *obj = jsR_newobject(J, JS_CSTRING);
js_Object *obj = jsR_newobject(J, JS_CSTRING, J->String_prototype);
obj->primitive.string = v;
return obj;
}

View File

@@ -86,7 +86,7 @@ js_Object *jsR_toobject(js_State *J, const js_Value *v);
js_Value jsR_toprimitive(js_State *J, const js_Value *v, int preferred);
/* jsproperty.c */
js_Object *jsR_newobject(js_State *J, js_Class type);
js_Object *jsR_newobject(js_State *J, js_Class type, js_Object *prototype);
js_Property *jsR_getownproperty(js_State *J, js_Object *obj, const char *name);
js_Property *jsR_getproperty(js_State *J, js_Object *obj, const char *name);
js_Property *jsR_setproperty(js_State *J, js_Object *obj, const char *name);

View File

@@ -129,12 +129,12 @@ found:
return parent;
}
js_Object *jsR_newobject(js_State *J, js_Class type)
js_Object *jsR_newobject(js_State *J, js_Class type, js_Object *prototype)
{
js_Object *obj = malloc(sizeof(js_Object));
obj->type = type;
obj->properties = &sentinel;
obj->prototype = NULL;
obj->prototype = prototype;
obj->primitive.number = 0;
obj->scope = NULL;
obj->function = NULL;

23
jsrun.c
View File

@@ -109,12 +109,12 @@ void js_pushglobal(js_State *J)
void js_newobject(js_State *J)
{
js_pushobject(J, jsR_newobject(J, JS_COBJECT));
js_pushobject(J, jsR_newobject(J, JS_COBJECT, J->Object_prototype));
}
void js_newarray(js_State *J)
{
js_pushobject(J, jsR_newobject(J, JS_CARRAY));
js_pushobject(J, jsR_newobject(J, JS_CARRAY, J->Array_prototype));
}
void js_pushcfunction(js_State *J, js_CFunction v)
@@ -334,7 +334,7 @@ static void jsR_callfunction(js_State *J, int n, js_Function *F, js_Environment
saveE = J->E;
J->E = jsR_newenvironment(J, jsR_newobject(J, JS_COBJECT), scope);
J->E = jsR_newenvironment(J, jsR_newobject(J, JS_COBJECT, NULL), scope);
for (i = 0; i < n; i++) {
js_Property *ref = js_decvar(J, F->params[i]);
if (i < n)
@@ -392,7 +392,7 @@ void jsR_dumpstack(js_State *J)
printf("stack {\n");
for (i = 0; i < top; ++i) {
putchar(i == bot ? '>' : ' ');
printf("% 3d: ", i);
printf("% 4d: ", i);
js_dumpvalue(J, stack[i]);
putchar('\n');
}
@@ -523,15 +523,22 @@ static void jsR_run(js_State *J, js_Function *F)
case OP_NEXTPROP:
obj = js_toobject(J, -2);
if (js_isundefined(J, -1))
ref = jsR_nextproperty(J, obj, NULL);
str = NULL;
else
ref = jsR_nextproperty(J, obj, js_tostring(J, -1));
str = js_tostring(J, -1);
ref = jsR_nextproperty(J, obj, str);
if (!ref && obj->prototype) {
obj = obj->prototype;
ref = jsR_nextproperty(J, obj, NULL);
}
js_pop(J, 2);
if (ref) {
js_pop(J, 1);
js_pushobject(J, obj);
js_pushliteral(J, ref->name);
js_pushboolean(J, 1);
} else {
js_pop(J, 2);
js_pushboolean(J, 0);
}
break;

View File

@@ -7,9 +7,10 @@ struct js_Environment
js_Object *variables;
};
void jsB_init(js_State *J);
js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer);
int jsR_loadscript(js_State *J, const char *filename, const char *source);
void jsR_error(js_State *J, const char *fmt, ...);
void js_call(js_State *J, int n);

View File

@@ -74,49 +74,15 @@ int js_dofile(js_State *J, const char *filename)
return rv;
}
static int jsB_print(js_State *J, int argc)
{
int i;
for (i = 1; i < argc; ++i) {
const char *s = js_tostring(J, i);
if (i > 1) putchar(' ');
fputs(s, stdout);
}
putchar('\n');
return 0;
}
static int jsB_eval(js_State *J, int argc)
{
const char *s;
if (!js_isstring(J, -1))
return 1;
// FIXME: return value if eval string is an expression
s = js_tostring(J, -1);
if (jsR_loadscript(J, "(eval)", s))
jsR_error(J, "SyntaxError (eval)");
js_dup(J, 0); /* copy this */
js_call(J, 0);
return 1;
}
js_State *js_newstate(void)
{
js_State *J = malloc(sizeof *J);
memset(J, 0, sizeof(*J));
J->G = jsR_newobject(J, JS_COBJECT);
J->G = jsR_newobject(J, JS_COBJECT, NULL);
J->E = jsR_newenvironment(J, J->G, NULL);
js_pushcfunction(J, jsB_eval);
js_setglobal(J, "eval");
js_pushcfunction(J, jsB_print);
js_setglobal(J, "print");
jsB_init(J);
return J;
}

View File

@@ -29,6 +29,13 @@ struct js_State
int strict;
/* runtime */
js_Object *Object_prototype;
js_Object *Array_prototype;
js_Object *Function_prototype;
js_Object *Boolean_prototype;
js_Object *Number_prototype;
js_Object *String_prototype;
js_Object *G;
js_Environment *E;