shithub: libmujs

Download patch

ref: c55b4e18bc30a3321179edf48cd42fcb3ccb6424
parent: 4c326a51a42436f9277cc86bf83d2e6dc4d3711e
author: Tor Andersson <tor@ccxvii.net>
date: Wed Jan 22 19:16:21 EST 2014

Implement instanceof expression.

--- a/jscompile.c
+++ b/jscompile.c
@@ -201,8 +201,10 @@
 			cexp(J, F, kv->b);
 			emit(J, F, OP_SETPROP);
 			emit(J, F, OP_POP);
+		} else {
+			// TODO: set/get
+			jsC_error(J, kv, "property setters and getters are not implemented");
 		}
-		// TODO: set, get
 		list = list->b;
 	}
 }
--- a/jscompile.h
+++ b/jscompile.h
@@ -1,7 +1,9 @@
 #ifndef js_compile_h
 #define js_compile_h
 
-enum
+typedef enum js_OpCode js_OpCode;
+
+enum js_OpCode
 {
 	OP_POP,		/* A -- */
 	OP_POP2,	/* A B -- */
--- a/jsrun.c
+++ b/jsrun.c
@@ -400,7 +400,7 @@
 	else if (obj->type == JS_CCFUNCTION)
 		jsR_callcfunction(J, n, obj->u.c.function);
 	else
-		js_typeerror(J, "not a function");
+		js_typeerror(J, "call: not a function");
 	BOT = savebot;
 }
 
@@ -451,7 +451,7 @@
 void js_savetry(js_State *J, short *pc)
 {
 	if (J->trylen == JS_TRYLIMIT)
-		js_error(J, "exception stack overflow");
+		js_error(J, "try: exception stack overflow");
 	J->trybuf[J->trylen].E = J->E;
 	J->trybuf[J->trylen].top = J->top;
 	J->trybuf[J->trylen].bot = J->bot;
@@ -512,7 +512,8 @@
 	const char **ST = F->strtab;
 	short *pcstart = F->code;
 	short *pc = F->code;
-	int opcode, offset;
+	js_OpCode opcode;
+	int offset;
 
 	const char *str;
 	js_Object *obj;
@@ -574,7 +575,7 @@
 			if (ref)
 				js_pushvalue(J, ref->value);
 			else
-				js_referenceerror(J, "%s", str);
+				js_referenceerror(J, "%s is not defined", str);
 			break;
 
 		case OP_SETVAR:
@@ -749,7 +750,9 @@
 		case OP_LE: b = js_compare(J); js_pushboolean(J, b <= 0); break;
 		case OP_GE: b = js_compare(J); js_pushboolean(J, b >= 0); break;
 
-		// OP_INSTANCEOF
+		case OP_INSTANCEOF:
+			js_instanceof(J);
+			break;
 
 		/* Equality */
 
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -296,6 +296,38 @@
 
 /* Non-trivial operations on values. These are implemented using the stack. */
 
+void js_instanceof(js_State *J)
+{
+	js_Object *O, *V;
+
+	if (!js_iscallable(J, -1))
+		js_typeerror(J, "instanceof: invalid operand");
+
+	if (!js_isobject(J, -2)) {
+		js_pop(J, 2);
+		js_pushboolean(J, 0);
+		return;
+	}
+	V = js_toobject(J, -2);
+
+	js_getproperty(J, -1, "prototype");
+	if (!js_isobject(J, -1))
+		js_typeerror(J, "instanceof: 'prototype' property is not an object");
+	O = js_toobject(J, -1);
+
+	while (V) {
+		V = V->prototype;
+		if (O == V) {
+			js_pop(J, 3);
+			js_pushboolean(J, 1);
+			return;
+		}
+	}
+
+	js_pop(J, 3);
+	js_pushboolean(J, 0);
+}
+
 void js_concat(js_State *J)
 {
 	js_Value va = js_toprimitive(J, -2, JS_HNONE);
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -92,6 +92,8 @@
 const char *jsV_numbertostring(js_State *J, double number);
 double jsV_stringtonumber(js_State *J, const char *string);
 
+void js_instanceof(js_State *J);
+
 /* jsproperty.c */
 js_Object *jsV_newobject(js_State *J, js_Class type, js_Object *prototype);
 js_Property *jsV_getownproperty(js_State *J, js_Object *obj, const char *name);