mirror of
https://github.com/ccxvii/mujs.git
synced 2026-02-06 01:41:37 +08:00
Set prototype internal property when creating objects.
This commit is contained in:
114
jsbuiltin.c
Normal file
114
jsbuiltin.c
Normal 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);
|
||||
}
|
||||
13
jsobject.c
13
jsobject.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
23
jsrun.c
@@ -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;
|
||||
|
||||
3
jsrun.h
3
jsrun.h
@@ -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);
|
||||
|
||||
|
||||
38
jsstate.c
38
jsstate.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user